Skip to content

LinearCellDemo

vtk-examples/Cxx/GeometricObjects/LinearCellDemo


Description

Linear cell types found in VTK.

The numbers define the ordering of the defining points.

Options are provided to show a wire frame (-w) or to add a back face color (-b). You can also remove the plinth with the (-n) option.

With the back face option selected, the back face color will be visible as the objects are semitransparent.

Other languages

See (Python), (PythonicAPI)

Question

If you have a question about this example, please use the VTK Discourse Forum

Code

LinearCellDemo.cxx

#include <vtkActor.h>
#include <vtkActor2D.h>
#include <vtkCamera.h>
#include <vtkCellArray.h>
#include <vtkCubeSource.h>
#include <vtkDataSetMapper.h>
#include <vtkGlyph3DMapper.h>
#include <vtkLabeledDataMapper.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPoints.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkProperty2D.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkTextMapper.h>
#include <vtkTextProperty.h>
#include <vtkUnstructuredGrid.h>

#include <vtkHexagonalPrism.h>
#include <vtkHexahedron.h>
#include <vtkLine.h>
#include <vtkPentagonalPrism.h>
#include <vtkPixel.h>
#include <vtkPolyLine.h>
#include <vtkPolyVertex.h>
#include <vtkPolygon.h>
#include <vtkPyramid.h>
#include <vtkQuad.h>
#include <vtkTetra.h>
#include <vtkTriangle.h>
#include <vtkTriangleStrip.h>
#include <vtkVertex.h>
#include <vtkVoxel.h>
#include <vtkWedge.h>

#include <vtk_cli11.h>
#include <vtk_fmt.h>
// clang-format off
#include VTK_FMT(fmt/format.h)
// clang-format on

#include <cstdlib>
#include <string>
#include <vector>

using cellPair =
    std::pair<vtkSmartPointer<vtkUnstructuredGrid>, std::array<double, 3>>;
using cellMap = std::map<std::string, cellPair>;

namespace {

/**
 * Make a map consisting of the unstructured grid name,
 *  the unstructured grid and it's orientation as
 *  Azimuth, Elevation and Zoom in degrees.
 *
 * @return The map.
 */
cellMap GetUnstructuredGrids();

// These functions return an vtkUnstructured grid corresponding to the object.
vtkNew<vtkUnstructuredGrid> MakeVertex();
vtkNew<vtkUnstructuredGrid> MakePolyVertex();
vtkNew<vtkUnstructuredGrid> MakeLine();
vtkNew<vtkUnstructuredGrid> MakePolyLine();
vtkNew<vtkUnstructuredGrid> MakeTriangle();
vtkNew<vtkUnstructuredGrid> MakeTriangleStrip();
vtkNew<vtkUnstructuredGrid> MakePolygon();
vtkNew<vtkUnstructuredGrid> MakePixel();
vtkNew<vtkUnstructuredGrid> MakeQuad();
vtkNew<vtkUnstructuredGrid> MakeTetra();
vtkNew<vtkUnstructuredGrid> MakeVoxel();
vtkNew<vtkUnstructuredGrid> MakeHexahedron();
vtkNew<vtkUnstructuredGrid> MakeWedge();
vtkNew<vtkUnstructuredGrid> MakePyramid();
vtkNew<vtkUnstructuredGrid> MakePentagonalPrism();
vtkNew<vtkUnstructuredGrid> MakeHexagonalPrism();

/**
 * Make a tile slightly larger or smaller than the bounds in the
 *   X and Z directions and thinner or thicker in the Y direction.
 *
 * A thickness_ratio of zero reduces the tile to an XZ plane.
 *
 * @param bounds - the bounds for the tile.
 * @param expansionFactor - the expansion factor in the XZ plane.
 * @param thicknessRatio - the thickness ratio in the Y direction, >= 0.
 * @return An actor corresponding to the tile.
 */
vtkNew<vtkActor> MakeTile(double* const& bounds,
                          double const& expansionFactor = 0.1,
                          double const& thicknessRatio = 0.05);

} // namespace

int main(int argc, char* argv[])
{
  CLI::App app{
      "Demonstrate the linear cell types found in VTK. "
      "The numbers define the ordering of the points making the cell."};

  // Define options
  std::string fileName;
  auto wireframeOn{false};
  app.add_flag("-w, --wireframe", wireframeOn, "Render a wireframe.");
  auto backfaceOn{false};
  app.add_flag("-b, --backface", backfaceOn,
               "Display the back face in a different colour.");
  auto plinthOff{false};
  app.add_flag("-n, --noPlinth", plinthOff, "Remove the plinth.");
  CLI11_PARSE(app, argc, argv);
  if (wireframeOn && backfaceOn)
  {
    std::cerr << "error: argument -b/--backface: not allowed with argument "
                 "-w/--wireframe"
              << std::endl;
    return EXIT_FAILURE;
  }

  vtkNew<vtkNamedColors> colors;

  // Create one sphere for all.
  vtkNew<vtkSphereSource> sphere;
  sphere->SetPhiResolution(21);
  sphere->SetThetaResolution(21);
  sphere->SetRadius(0.04);

  auto cells = GetUnstructuredGrids();

  // clang-format off
  std::array<std::string, 16> keys = {
      "VTK_VERTEX (=1)",            "VTK_POLY_VERTEX (=2)",
      "VTK_LINE (=3)",              "VTK_POLY_LINE (=4)",
      "VTK_TRIANGLE (=5)",          "VTK_TRIANGLE_STRIP (=6)",
      "VTK_POLYGON (=7)",           "VTK_PIXEL (=8)",
      "VTK_QUAD (=9)",              "VTK_TETRA (=10)",
      "VTK_VOXEL (=11)",            "VTK_HEXAHEDRON (=12)",
      "VTK_WEDGE (=13)",            "VTK_PYRAMID (=14)",
      "VTK_PENTAGONAL_PRISM (=15)", "VTK_HEXAGONAL_PRISM (=16)"};
  // clang-format on

  std::vector<std::string> addPlinth = {
      "VTK_TETRA (=10)",           "VTK_VOXEL (=11)",
      "VTK_HEXAHEDRON (=12)",      "VTK_WEDGE (=13)",
      "VTK_PYRAMID (=14)",         "VTK_PENTAGONAL_PRISM (=15)",
      "VTK_HEXAGONAL_PRISM (=16)",
  };
  std::vector<std::string> lines{"VTK_LINE (=3)", "VTK_POLY_LINE (=4)"};

  // Set up the viewports.
  auto gridRowDimensions = 4;
  auto gridColumnDimensions = 4;
  auto rendererSize = 300;
  std::array<int, 2> windowSize{gridColumnDimensions * rendererSize,
                                gridRowDimensions * rendererSize};

  auto blank = cells.size();
  std::vector<std::string> blankViewports;

  std::map<std::string, std::array<double, 4>> viewports;
  for (int row = 0; row < gridRowDimensions; row++)
  {
    for (int col = 0; col < gridColumnDimensions; col++)
    {
      int index = row * gridColumnDimensions + col;

      // Set the renderer's viewport dimensions (xmin, ymin, xmax, ymax)
      //  within the render window.
      // Note that for the Y values, we need to subtract the row index
      //  from grid rows because the viewport Y axis points upwards
      //  and we want to draw the grid from top to down.
      std::array<double, 4> viewport{
          static_cast<double>(col) / gridColumnDimensions,
          static_cast<double>(gridRowDimensions - row - 1) / gridRowDimensions,
          static_cast<double>(col + 1) / gridColumnDimensions,
          static_cast<double>(gridRowDimensions - row) / gridRowDimensions};
      // std::cout << viewport[0] << " " << viewport[1]
      //           << " " << viewport[2] << " "<< viewport[3] << std::endl;
      if (index < blank)
      {
        viewports[keys[index]] = viewport;
      }
      else
      {
        auto s = fmt::format("vp_{:d}_{:d}", col, row);
        viewports[s] = viewport;
        blankViewports.push_back(s);
      }
    }
  }

  // Create one text property for all.
  vtkNew<vtkTextProperty> textProperty;
  textProperty->SetFontSize(int(rendererSize / 18));
  textProperty->BoldOn();
  textProperty->SetJustificationToCentered();
  textProperty->SetColor(colors->GetColor3d("Black").GetData());

  vtkNew<vtkTextProperty> labelProperty;
  labelProperty->SetFontSize(int(rendererSize / 12));
  labelProperty->BoldOn();
  labelProperty->ShadowOn();
  labelProperty->SetJustificationToCentered();
  labelProperty->SetColor(colors->GetColor3d("DeepPink").GetData());

  vtkNew<vtkProperty> backProperty;
  backProperty->SetColor(colors->GetColor3d("DodgerBlue").GetData());

  std::map<std::string, vtkSmartPointer<vtkRenderer>> renderers;

  vtkNew<vtkRenderWindow> renWin;
  renWin->SetWindowName("LinearCellDemo");
  renWin->SetSize(windowSize.data());

  vtkNew<vtkRenderWindowInteractor> iRen;
  iRen->SetRenderWindow(renWin);

  // Create and link the mappers, actors and renderers together.
  for (const auto& key : keys)
  {
    std::cout << "Creating: " << key << std::endl;

    vtkNew<vtkTextMapper> textMapper;
    textMapper->SetTextProperty(textProperty);
    textMapper->SetInput(key.c_str());
    vtkNew<vtkActor2D> textActor;
    textActor->SetMapper(textMapper);
    textActor->SetPosition(rendererSize / 2.0, 8);

    vtkNew<vtkDataSetMapper> mapper;
    mapper->SetInputData(cells[key].first);
    vtkNew<vtkActor> actor;
    actor->SetMapper(mapper);
    if (wireframeOn ||
        std::find(lines.cbegin(), lines.cend(), key) != lines.cend())
    {
      std::cout << "wireframe on" << std::endl;
      actor->GetProperty()->SetRepresentationToWireframe();
      actor->GetProperty()->SetLineWidth(2);
      actor->GetProperty()->SetOpacity(1);
      actor->GetProperty()->SetColor(colors->GetColor3d("Black").GetData());
    }
    else
    {
      actor->GetProperty()->EdgeVisibilityOn();
      actor->GetProperty()->SetLineWidth(3);
      actor->GetProperty()->SetColor(colors->GetColor3d("Snow").GetData());
      if (backfaceOn)
      {
        actor->GetProperty()->SetOpacity(0.4);
        actor->SetBackfaceProperty(backProperty);
        backProperty->SetOpacity(0.6);
      }
      else
      {
        actor->GetProperty()->SetOpacity(0.8);
      }
    }

    // Label the points.
    vtkNew<vtkLabeledDataMapper> labelMapper;
    labelMapper->SetInputData(cells[key].first);
    labelMapper->SetLabelTextProperty(labelProperty);
    vtkNew<vtkActor2D> labelActor;
    labelActor->SetMapper(labelMapper);

    // Glyph the points.
    vtkNew<vtkGlyph3DMapper> pointMapper;
    pointMapper->SetInputData(cells[key].first);
    pointMapper->SetSourceConnection(sphere->GetOutputPort());
    pointMapper->ScalingOff();
    pointMapper->ScalarVisibilityOff();

    vtkNew<vtkActor> pointActor;
    pointActor->SetMapper(pointMapper);
    pointActor->GetProperty()->SetColor(colors->GetColor3d("Gold").GetData());

    vtkNew<vtkRenderer> renderer;
    renderer->SetBackground(colors->GetColor3d("LightSteelBlue").GetData());
    renderer->SetViewport(viewports[key].data());

    renderer->AddViewProp(textActor);
    renderer->AddViewProp(actor);
    renderer->AddViewProp(labelActor);
    renderer->AddViewProp(pointActor);
    if (!plinthOff)
    {
      if (std::find(addPlinth.cbegin(), addPlinth.cend(), key) !=
          addPlinth.cend())
      {
        auto tileActor = MakeTile(cells[key].first->GetBounds(), 0.5, 0.05);
        tileActor->GetProperty()->SetColor(
            colors->GetColor3d("Lavender").GetData());
        tileActor->GetProperty()->SetOpacity(0.3);
        renderer->AddViewProp(tileActor);
      }
    }

    renderer->ResetCamera();
    renderer->GetActiveCamera()->Azimuth(cells[key].second[0]);
    renderer->GetActiveCamera()->Elevation(cells[key].second[1]);
    renderer->GetActiveCamera()->Dolly(cells[key].second[2]);
    renderer->ResetCameraClippingRange();

    renWin->AddRenderer(renderer);
    renderers[key] = renderer;
  }

  for (const auto& key : blankViewports)
  {
    vtkNew<vtkRenderer> renderer;
    renderer->SetBackground(colors->GetColor3d("LightSteelBlue").GetData());
    renderer->SetViewport(viewports[key].data());
    renWin->AddRenderer(renderer);
    renderers[key] = renderer;
  }

  iRen->Initialize();
  renWin->Render();
  iRen->Start();

  return EXIT_SUCCESS;
}

namespace {

cellMap GetUnstructuredGrids()
{
  cellMap cells;

  cells["VTK_VERTEX (=1)"] = cellPair(MakeVertex(), {30, -30, 0.1});
  cells["VTK_POLY_VERTEX (=2)"] = cellPair(MakePolyVertex(), {30, -30, 0.8});
  cells["VTK_LINE (=3)"] = cellPair(MakeLine(), {30, -30, 0.4});
  cells["VTK_POLY_LINE (=4)"] = cellPair(MakePolyLine(), {30, -30, 1.0});
  cells["VTK_TRIANGLE (=5)"] = cellPair(MakeTriangle(), {30, -30, 0.7});
  cells["VTK_TRIANGLE_STRIP (=6)"] =
      cellPair(MakeTriangleStrip(), {30, -30, 1.1});
  cells["VTK_POLYGON (=7)"] = cellPair(MakePolygon(), {0, -45, 1.0});
  cells["VTK_PIXEL (=8)"] = cellPair(MakePixel(), {0, -45, 1.0});
  cells["VTK_QUAD (=9)"] = cellPair(MakeQuad(), {0, -45, 1.0});
  cells["VTK_TETRA (=10)"] = cellPair(MakeTetra(), {20, 20, 1.0});
  cells["VTK_VOXEL (=11)"] = cellPair(MakeVoxel(), {-22.5, 15, 0.95});
  cells["VTK_HEXAHEDRON (=12)"] = cellPair(MakeHexahedron(), {-22.5, 15, 0.95});
  cells["VTK_WEDGE (=13)"] = cellPair(MakeWedge(), {-30, 15, 1.0});
  cells["VTK_PYRAMID (=14)"] = cellPair(MakePyramid(), {-60, 15, 1.0});
  cells["VTK_PENTAGONAL_PRISM (=15)"] =
      cellPair(MakePentagonalPrism(), {-60, 10, 1.0});
  cells["VTK_HEXAGONAL_PRISM (=16)"] =
      cellPair(MakeHexagonalPrism(), {-60, 15, 1.0});

  return cells;
}

vtkNew<vtkUnstructuredGrid> MakeVertex()
{
  // A vertex is a cell that represents a 3D point.
  auto numberOfVertices = 1;

  vtkNew<vtkPoints> points;
  points->InsertNextPoint(0, 0, 0);

  vtkNew<vtkVertex> vertex;
  for (auto i = 0; i < numberOfVertices; ++i)
  {
    vertex->GetPointIds()->SetId(i, i);
  }
  vtkNew<vtkUnstructuredGrid> ug;
  ug->SetPoints(points);
  ug->InsertNextCell(vertex->GetCellType(), vertex->GetPointIds());

  return ug;
}

vtkNew<vtkUnstructuredGrid> MakePolyVertex()
{
  // A polyvertex is a cell that represents a set of 0D vertices.
  auto numberOfVertices = 6;

  vtkNew<vtkPoints> points;
  points->InsertNextPoint(0, 0, 0);
  points->InsertNextPoint(1, 0, 0);
  points->InsertNextPoint(0, 1, 0);
  points->InsertNextPoint(0, 0, 1);
  points->InsertNextPoint(1, 0, 0.4);
  points->InsertNextPoint(0, 1, 0.6);

  vtkNew<vtkPolyVertex> polyVertex;
  polyVertex->GetPointIds()->SetNumberOfIds(numberOfVertices);

  for (auto i = 0; i < numberOfVertices; ++i)
  {
    polyVertex->GetPointIds()->SetId(i, i);
  }

  vtkNew<vtkUnstructuredGrid> ug;
  ug->SetPoints(points);
  ug->InsertNextCell(polyVertex->GetCellType(), polyVertex->GetPointIds());

  return ug;
}

vtkNew<vtkUnstructuredGrid> MakeLine()
{
  // A line is a cell that represents a 1D point.
  auto numberOfVertices = 2;

  vtkNew<vtkPoints> points;
  points->InsertNextPoint(0, 0, 0);
  points->InsertNextPoint(0.5, 0.5, 0);

  vtkNew<vtkLine> line;
  for (auto i = 0; i < numberOfVertices; ++i)
  {
    line->GetPointIds()->SetId(i, i);
  }

  vtkNew<vtkUnstructuredGrid> ug;
  ug->SetPoints(points);
  ug->InsertNextCell(line->GetCellType(), line->GetPointIds());

  return ug;
}

vtkNew<vtkUnstructuredGrid> MakePolyLine()
{
  // A polyline is a cell that represents a set of 1D lines.
  auto numberOfVertices = 5;

  vtkNew<vtkPoints> points;
  points->InsertNextPoint(0, 0.5, 0);
  points->InsertNextPoint(0.5, 0, 0);
  points->InsertNextPoint(1, 0.3, 0);
  points->InsertNextPoint(1.5, 0.4, 0);
  points->InsertNextPoint(2.0, 0.4, 0);

  vtkNew<vtkPolyLine> polyline;
  polyline->GetPointIds()->SetNumberOfIds(numberOfVertices);

  for (auto i = 0; i < numberOfVertices; ++i)
  {
    polyline->GetPointIds()->SetId(i, i);
  }

  vtkNew<vtkUnstructuredGrid> ug;
  ug->SetPoints(points);
  ug->InsertNextCell(polyline->GetCellType(), polyline->GetPointIds());

  return ug;
}

vtkNew<vtkUnstructuredGrid> MakeTriangle()
{
  // A triangle is a cell that represents a triangle.
  auto numberOfVertices = 3;

  vtkNew<vtkPoints> points;
  points->InsertNextPoint(0, 0, 0);
  points->InsertNextPoint(0.5, 0.5, 0);
  points->InsertNextPoint(0.2, 1, 0);

  vtkNew<vtkTriangle> triangle;
  for (auto i = 0; i < numberOfVertices; ++i)
  {
    triangle->GetPointIds()->SetId(i, i);
  }

  vtkNew<vtkUnstructuredGrid> ug;
  ug->SetPoints(points);
  ug->InsertNextCell(triangle->GetCellType(), triangle->GetPointIds());

  return ug;
}

vtkNew<vtkUnstructuredGrid> MakeTriangleStrip()
{
  // A triangle is a cell that represents a triangle strip.
  auto numberOfVertices = 10;

  vtkNew<vtkPoints> points;
  points->InsertNextPoint(0, 0, 0);
  points->InsertNextPoint(1, -0.1, 0);
  points->InsertNextPoint(0.5, 1, 0);
  points->InsertNextPoint(2.0, -0.1, 0);
  points->InsertNextPoint(1.5, 0.8, 0);
  points->InsertNextPoint(3.0, 0, 0);
  points->InsertNextPoint(2.5, 0.9, 0);
  points->InsertNextPoint(4.0, -0.2, 0);
  points->InsertNextPoint(3.5, 0.8, 0);
  points->InsertNextPoint(4.5, 1.1, 0);

  vtkNew<vtkTriangleStrip> trianglestrip;
  trianglestrip->GetPointIds()->SetNumberOfIds(numberOfVertices);
  for (auto i = 0; i < numberOfVertices; ++i)
  {
    trianglestrip->GetPointIds()->SetId(i, i);
  }

  vtkNew<vtkUnstructuredGrid> ug;
  ug->SetPoints(points);
  ug->InsertNextCell(trianglestrip->GetCellType(),
                     trianglestrip->GetPointIds());

  return ug;
}

vtkNew<vtkUnstructuredGrid> MakePolygon()
{
  // A polygon is a cell that represents a polygon.
  auto numberOfVertices = 6;

  vtkNew<vtkPoints> points;
  points->InsertNextPoint(0, 0, 0);
  points->InsertNextPoint(1, -0.1, 0);
  points->InsertNextPoint(0.8, 0.5, 0);
  points->InsertNextPoint(1, 1, 0);
  points->InsertNextPoint(0.6, 1.2, 0);
  points->InsertNextPoint(0, 0.8, 0);

  vtkNew<vtkPolygon> polygon;
  polygon->GetPointIds()->SetNumberOfIds(numberOfVertices);
  for (auto i = 0; i < numberOfVertices; ++i)
  {
    polygon->GetPointIds()->SetId(i, i);
  }

  vtkNew<vtkUnstructuredGrid> ug;
  ug->SetPoints(points);
  ug->InsertNextCell(polygon->GetCellType(), polygon->GetPointIds());

  return ug;
}

vtkNew<vtkUnstructuredGrid> MakePixel()

{
  // A pixel is a cell that represents a pixel.
  auto numberOfVertices = 4;

  vtkNew<vtkPixel> pixel;
  pixel->GetPoints()->SetPoint(0, 0, 0, 0);
  pixel->GetPoints()->SetPoint(1, 1, 0, 0);
  pixel->GetPoints()->SetPoint(2, 0, 1, 0);
  pixel->GetPoints()->SetPoint(3, 1, 1, 0);

  for (auto i = 0; i < numberOfVertices; ++i)
  {
    pixel->GetPointIds()->SetId(i, i);
  }

  vtkNew<vtkUnstructuredGrid> ug;
  ug->SetPoints(pixel->GetPoints());
  ug->InsertNextCell(pixel->GetCellType(), pixel->GetPointIds());

  return ug;
}

vtkNew<vtkUnstructuredGrid> MakeQuad()

{
  // A quad is a cell that represents a quad.
  auto numberOfVertices = 4;

  vtkNew<vtkQuad> quad;
  quad->GetPoints()->SetPoint(0, 0, 0, 0);
  quad->GetPoints()->SetPoint(1, 1, 0, 0);
  quad->GetPoints()->SetPoint(2, 1, 1, 0);
  quad->GetPoints()->SetPoint(3, 0, 1, 0);

  for (auto i = 0; i < numberOfVertices; ++i)
  {
    quad->GetPointIds()->SetId(i, i);
  }

  vtkNew<vtkUnstructuredGrid> ug;
  ug->SetPoints(quad->GetPoints());
  ug->InsertNextCell(quad->GetCellType(), quad->GetPointIds());

  return ug;
}

vtkNew<vtkUnstructuredGrid> MakeTetra()
{
  // Make a tetrahedron.
  auto numberOfVertices = 4;

  // vtkNew<vtkPoints> points;
  // points->InsertNextPoint(0, 0, 0);
  // points->InsertNextPoint(1, 0, 0);
  // points->InsertNextPoint(1, 1, 0);
  // points->InsertNextPoint(0, 1, 1);

  // Rotate the above points -90° about the X-axis.
  vtkNew<vtkPoints> points;
  points->InsertNextPoint(0, 0, 0);
  points->InsertNextPoint(1, 0, 0);
  points->InsertNextPoint(1, 0, -1);
  points->InsertNextPoint(0, 1, -1);

  vtkNew<vtkTetra> tetra;
  for (auto i = 0; i < numberOfVertices; ++i)
  {
    tetra->GetPointIds()->SetId(i, i);
  }

  vtkNew<vtkCellArray> cellArray;
  cellArray->InsertNextCell(tetra);

  vtkNew<vtkUnstructuredGrid> unstructuredGrid;
  unstructuredGrid->SetPoints(points);
  unstructuredGrid->SetCells(VTK_TETRA, cellArray);

  return unstructuredGrid;
}

vtkNew<vtkUnstructuredGrid> MakeVoxel()
{
  // A voxel is a representation of a regular grid in 3-D space.
  auto numberOfVertices = 8;

  vtkNew<vtkPoints> points;
  points->InsertNextPoint(0, 0, 0);
  points->InsertNextPoint(1, 0, 0);
  points->InsertNextPoint(0, 1, 0);
  points->InsertNextPoint(1, 1, 0);
  points->InsertNextPoint(0, 0, 1);
  points->InsertNextPoint(1, 0, 1);
  points->InsertNextPoint(0, 1, 1);
  points->InsertNextPoint(1, 1, 1);

  vtkNew<vtkVoxel> voxel;
  for (auto i = 0; i < numberOfVertices; ++i)
  {
    voxel->GetPointIds()->SetId(i, i);
  }

  vtkNew<vtkUnstructuredGrid> ug;
  ug->SetPoints(points);
  ug->InsertNextCell(voxel->GetCellType(), voxel->GetPointIds());

  return ug;
}

vtkNew<vtkUnstructuredGrid> MakeHexahedron()
{
  // A regular hexagon (cube) with all faces square and three squares around
  // each vertex is created below.

  // Set up the coordinates of eight points
  // (the two faces must be in counter-clockwise
  // order as viewed from the outside).

  auto numberOfVertices = 8;

  // Create the points
  vtkNew<vtkPoints> points;
  points->InsertNextPoint(0.0, 0.0, 0.0);
  points->InsertNextPoint(1.0, 0.0, 0.0);
  points->InsertNextPoint(1.0, 1.0, 0.0);
  points->InsertNextPoint(0.0, 1.0, 0.0);
  points->InsertNextPoint(0.0, 0.0, 1.0);
  points->InsertNextPoint(1.0, 0.0, 1.0);
  points->InsertNextPoint(1.0, 1.0, 1.0);
  points->InsertNextPoint(0.0, 1.0, 1.0);

  // Create a hexahedron from the points
  vtkNew<vtkHexahedron> hex;
  for (auto i = 0; i < numberOfVertices; ++i)
  {
    hex->GetPointIds()->SetId(i, i);
  }

  // Add the points and hexahedron to an unstructured grid
  vtkNew<vtkUnstructuredGrid> uGrid;
  uGrid->SetPoints(points);
  uGrid->InsertNextCell(hex->GetCellType(), hex->GetPointIds());

  return uGrid;
}

vtkNew<vtkUnstructuredGrid> MakeWedge()
{

  // A wedge consists of two triangular ends and three rectangular faces.

  auto numberOfVertices = 6;

  // vtkNew<vtkPoints> points;
  // points->InsertNextPoint(0, 1, 0);
  // points->InsertNextPoint(0, 0, 0);
  // points->InsertNextPoint(0, 0.5, 0.5);
  // points->InsertNextPoint(1, 1, 0);
  // points->InsertNextPoint(1, 0.0, 0.0);
  // points->InsertNextPoint(1, 0.5, 0.5);

  // Rotate the above points -90° about the X-axis
  //  and translate -1 along the Y-axis.
  vtkNew<vtkPoints> points;
  points->InsertNextPoint(0, 0, 0);
  points->InsertNextPoint(0, 0, 1);
  points->InsertNextPoint(0, 0.5, 0.5);
  points->InsertNextPoint(1, 0, 0);
  points->InsertNextPoint(1, 0, 1);
  points->InsertNextPoint(1, 0.5, 0.5);

  vtkNew<vtkWedge> wedge;
  for (auto i = 0; i < numberOfVertices; ++i)
  {
    wedge->GetPointIds()->SetId(i, i);
  }

  vtkNew<vtkUnstructuredGrid> ug;
  ug->SetPoints(points);
  ug->InsertNextCell(wedge->GetCellType(), wedge->GetPointIds());

  return ug;
}

vtkNew<vtkUnstructuredGrid> MakePyramid()
{
  // Make a regular square pyramid.
  auto numberOfVertices = 5;

  vtkNew<vtkPoints> points;

  // float p0[3] = {1.0, 1.0, 0.0};
  // float p1[3] = {-1.0, 1.0, 0.0};
  // float p2[3] = {-1.0, -1.0, 0.0};
  // float p3[3] = {1.0, -1.0, 0.0};
  // float p4[3] = {0.0, 0.0, 1.0};

  // Rotate the above points -90° about the X-axis.
  float p0[3] = {1.0, 0.0, -1.0};
  float p1[3] = {-1.0, 0.0, -1.0};
  float p2[3] = {-1.0, 0.0, 1.0};
  float p3[3] = {1.0, 0.0, 1.0};
  float p4[3] = {0.0, 2.0, 0.0};

  points->InsertNextPoint(p0);
  points->InsertNextPoint(p1);
  points->InsertNextPoint(p2);
  points->InsertNextPoint(p3);
  points->InsertNextPoint(p4);

  vtkNew<vtkPyramid> pyramid;
  for (auto i = 0; i < numberOfVertices; ++i)
  {
    pyramid->GetPointIds()->SetId(i, i);
  }

  vtkNew<vtkUnstructuredGrid> ug;
  ug->SetPoints(points);
  ug->InsertNextCell(pyramid->GetCellType(), pyramid->GetPointIds());

  return ug;
}
vtkNew<vtkUnstructuredGrid> MakePentagonalPrism()
{
  auto numberOfVertices = 10;

  vtkNew<vtkPentagonalPrism> pentagonalPrism;

  double scale = 2.0;
  pentagonalPrism->GetPoints()->SetPoint(0, 11 / scale, 10 / scale, 10 / scale);
  pentagonalPrism->GetPoints()->SetPoint(1, 13 / scale, 10 / scale, 10 / scale);
  pentagonalPrism->GetPoints()->SetPoint(2, 14 / scale, 12 / scale, 10 / scale);
  pentagonalPrism->GetPoints()->SetPoint(3, 12 / scale, 14 / scale, 10 / scale);
  pentagonalPrism->GetPoints()->SetPoint(4, 10 / scale, 12 / scale, 10 / scale);
  pentagonalPrism->GetPoints()->SetPoint(5, 11 / scale, 10 / scale, 14 / scale);
  pentagonalPrism->GetPoints()->SetPoint(6, 13 / scale, 10 / scale, 14 / scale);
  pentagonalPrism->GetPoints()->SetPoint(7, 14 / scale, 12 / scale, 14 / scale);
  pentagonalPrism->GetPoints()->SetPoint(8, 12 / scale, 14 / scale, 14 / scale);
  pentagonalPrism->GetPoints()->SetPoint(9, 10 / scale, 12 / scale, 14 / scale);

  for (auto i = 0; i < numberOfVertices; ++i)
  {
    pentagonalPrism->GetPointIds()->SetId(i, i);
  }

  vtkNew<vtkUnstructuredGrid> ug;
  ug->SetPoints(pentagonalPrism->GetPoints());
  ug->InsertNextCell(pentagonalPrism->GetCellType(),
                     pentagonalPrism->GetPointIds());

  return ug;
}

vtkNew<vtkUnstructuredGrid> MakeHexagonalPrism()
{
  auto numberOfVertices = 12;

  vtkNew<vtkHexagonalPrism> hexagonalPrism;

  double scale = 2.0;
  hexagonalPrism->GetPoints()->SetPoint(0, 11 / scale, 10 / scale, 10 / scale);
  hexagonalPrism->GetPoints()->SetPoint(1, 13 / scale, 10 / scale, 10 / scale);
  hexagonalPrism->GetPoints()->SetPoint(2, 14 / scale, 12 / scale, 10 / scale);
  hexagonalPrism->GetPoints()->SetPoint(3, 13 / scale, 14 / scale, 10 / scale);
  hexagonalPrism->GetPoints()->SetPoint(4, 11 / scale, 14 / scale, 10 / scale);
  hexagonalPrism->GetPoints()->SetPoint(5, 10 / scale, 12 / scale, 10 / scale);
  hexagonalPrism->GetPoints()->SetPoint(6, 11 / scale, 10 / scale, 14 / scale);
  hexagonalPrism->GetPoints()->SetPoint(7, 13 / scale, 10 / scale, 14 / scale);
  hexagonalPrism->GetPoints()->SetPoint(8, 14 / scale, 12 / scale, 14 / scale);
  hexagonalPrism->GetPoints()->SetPoint(9, 13 / scale, 14 / scale, 14 / scale);
  hexagonalPrism->GetPoints()->SetPoint(10, 11 / scale, 14 / scale, 14 / scale);
  hexagonalPrism->GetPoints()->SetPoint(11, 10 / scale, 12 / scale, 14 / scale);

  for (auto i = 0; i < numberOfVertices; ++i)
  {
    hexagonalPrism->GetPointIds()->SetId(i, i);
  }

  vtkNew<vtkUnstructuredGrid> ug;
  ug->SetPoints(hexagonalPrism->GetPoints());
  ug->InsertNextCell(hexagonalPrism->GetCellType(),
                     hexagonalPrism->GetPointIds());

  return ug;
}

/**
 * Make a tile slightly larger or smaller than the bounds in the
 *   X and Z directions and thinner or thicker in the Y direction.
 *
 * A thickness_ratio of zero reduces the tile to an XZ plane.
 *
 * @param bounds - the bounds for the tile.
 * @param expansionFactor - the expansion factor in the XZ plane.
 * @param thicknessRatio - the thickness ratio in the Y direction, >= 0.
 * @return An actor corresponding to the tile.
 */
vtkNew<vtkActor> MakeTile(double* const& bounds, double const& expansionFactor,
                          double const& thicknessRatio)
{
  std::vector<double> d_xyz = {bounds[1] - bounds[0], bounds[3] - bounds[2],
                               bounds[5] - bounds[4]};
  auto thickness = d_xyz[2] * std::abs(thicknessRatio);
  std::vector<double> center = {(bounds[1] + bounds[0]) / 2.0,
                                bounds[2] - thickness / 2.0,
                                (bounds[5] + bounds[4]) / 2.0};
  auto x_length = bounds[1] - bounds[0] + (d_xyz[0] * expansionFactor);
  auto z_length = bounds[5] - bounds[4] + (d_xyz[2] * expansionFactor);

  vtkNew<vtkCubeSource> plane;
  plane->SetCenter(center[0], center[1], center[2]);
  plane->SetXLength(x_length);
  plane->SetYLength(thickness);
  plane->SetZLength(z_length);

  vtkNew<vtkPolyDataMapper> planeMapper;
  planeMapper->SetInputConnection(plane->GetOutputPort());

  vtkNew<vtkActor> planeActor;
  planeActor->SetMapper(planeMapper);

  return planeActor;
}
} // namespace

CMakeLists.txt

cmake_minimum_required(VERSION 3.12 FATAL_ERROR)

project(LinearCellDemo)

find_package(VTK COMPONENTS 
  CommonColor
  CommonCore
  CommonDataModel
  FiltersSources
  InteractionStyle
  RenderingContextOpenGL2
  RenderingCore
  RenderingFreeType
  RenderingGL2PSOpenGL2
  RenderingLabel
  RenderingOpenGL2
  cli11
)

if (NOT VTK_FOUND)
  message(FATAL_ERROR "LinearCellDemo: Unable to find the VTK build folder.")
endif()

# Prevent a "command line is too long" failure in Windows.
set(CMAKE_NINJA_FORCE_RESPONSE_FILE "ON" CACHE BOOL "Force Ninja to use response files.")
add_executable(LinearCellDemo MACOSX_BUNDLE LinearCellDemo.cxx )
  target_link_libraries(LinearCellDemo PRIVATE ${VTK_LIBRARIES}
)
# vtk_module_autoinit is needed
vtk_module_autoinit(
  TARGETS LinearCellDemo
  MODULES ${VTK_LIBRARIES}
)

Download and Build LinearCellDemo

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

cd LinearCellDemo/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:

./LinearCellDemo

WINDOWS USERS

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