Skip to content

LinearCellsDemo

Repository source: LinearCellsDemo


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. If you want a single object, use -o followed by the object number.

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

LinearCellsDemo.cxx

#include <vtkActor.h>
#include <vtkActor2D.h>
#include <vtkAxesActor.h>
#include <vtkCamera.h>
#include <vtkCellArray.h>
#include <vtkCubeSource.h>
#include <vtkDataSetMapper.h>
#include <vtkGlyph3DMapper.h>
#include <vtkInteractorStyleSwitch.h>
#include <vtkLabeledDataMapper.h>
#include <vtkLightKit.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkOrientationMarkerWidget.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 <vtkVersion.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

#if VTK_VERSION_NUMBER >= 90020210809ULL
#define VTK_HAS_COW 1
#endif

#if VTK_HAS_COW
#include <vtkCameraOrientationWidget.h>
#endif

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

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

namespace {

/**
 * Link the unstructured grid number to the unstructured grid name.
 *
 * @return The map : {index number, unstructured grid name}
 */
std::map<unsigned int, std::string> SpecifyObjects();

/**
 * 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.
 * @param shiftY - used to shift the centre of the plinth in the Y-direction.
 * @return An actor corresponding to the tile.
 */
vtkNew<vtkActor> MakeTile(double const bounds[],
                          double const& expansionFactor = 0.5,
                          double const& thicknessRatio = 0.05,
                          double shiftY = -0.05);

vtkNew<vtkTextProperty> GetTextProperty();
vtkNew<vtkTextProperty> GetLabelProperty();
vtkNew<vtkProperty> GetBackFaceProperty();
vtkNew<vtkProperty> GetPointActorProperty();
vtkNew<vtkProperty> GetActorProperty();
vtkNew<vtkProperty> GetTileProperty();

} // 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
  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.");
  unsigned int objectNum = -1;
  app.add_option("-o, --object_number", objectNum,
                 "The number corresponding to the object.");
  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;
  }

  auto objects = SpecifyObjects();
  // The order here should match the order in specify_objects().
  std::vector<unsigned int> objectOrder{1, 2,  3,  4,  5,  6,  7,  8,
                                        9, 10, 11, 12, 13, 14, 15, 16};

  // Check for a single object.
  auto singleObject = false;
  if (objectNum != -1)
  {
    if (std::count(objectOrder.cbegin(), objectOrder.cend(), objectNum) > 0)
    {
      singleObject = true;
    }
    else
    {
      std::cerr << "Object not found.\n"
                   "Please enter the number corresponding to the object.\n"
                << "Available objects are:" << std::endl;
      for (auto obj : objectOrder)
      {
        std::cerr << fmt::format("{:s} (={:d})", objects[obj], obj)
                  << std::endl;
      }
      return EXIT_FAILURE;
    }
  }
  else
  {
    singleObject = false;
  }

  vtkNew<vtkNamedColors> colors;

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

  auto cells = GetUnstructuredGrids();
  // The text to be displayed in the viewport.
  std::vector<std::string> names;
  //  The keys of the objects selected for display.
  std::vector<unsigned int> keys;
  if (singleObject)
  {
    names.push_back(fmt::format("{:s} (={:d})", objects[objectNum], objectNum));
    keys.push_back(objectNum);
  }
  else
  {
    for (auto obj : objectOrder)
    {
      names.push_back(fmt::format("{:s} (={:d})", objects[obj], obj));
      keys.push_back(obj);
    }
  }

  std::vector<unsigned int> addPlinth{10, 11, 12, 13, 14, 15, 16};
  std::vector<unsigned int> lines{3, 4};

  // Set up the viewports.
  auto gridRowDimensions = 4;
  auto gridColumnDimensions = 4;
  auto rendererSize = 300;
  if (singleObject)
  {
    gridRowDimensions = 1;
    gridColumnDimensions = 1;
    rendererSize = 1200;
  }
  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[names[index]] = viewport;
      }
      else
      {
        auto s = fmt::format("vp_{:d}_{:d}", col, row);
        viewports[s] = viewport;
        blankViewports.push_back(s);
      }
    }
  }

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

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

  vtkNew<vtkRenderWindowInteractor> iRen;
  iRen->SetRenderWindow(renWin);
  auto is = vtkInteractorStyleSwitch::SafeDownCast(iRen->GetInteractorStyle());
  if (is)
  {
    is->SetCurrentStyleToTrackballCamera();
  }

  // Create and link the mappers, actors and renderers together.
  std::string singleObjectName{""};
  unsigned int idx = 0;
  for (const auto& key : keys)
  {
    std::cout << "Creating: " << names[idx] << std::endl;

    if (singleObject)
    {
      singleObjectName = names[idx];
    }

    auto textProperty = GetTextProperty();
    if (singleObject)
    {
      textProperty->SetFontSize(int(rendererSize / 28));
    }
    else
    {
      textProperty->SetFontSize(int(rendererSize / 24));
    }

    vtkNew<vtkTextMapper> textMapper;
    textMapper->SetTextProperty(textProperty);
    textMapper->SetInput(names[idx].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);
    actor->SetProperty(GetActorProperty());

    if (wireframeOn ||
        std::find(lines.cbegin(), lines.cend(), key) != lines.cend())
    {
      actor->GetProperty()->SetRepresentationToWireframe();
      actor->GetProperty()->SetLineWidth(2);
      actor->GetProperty()->SetOpacity(1);
      actor->GetProperty()->SetColor(colors->GetColor3d("Black").GetData());
    }
    else
    {
      if (backfaceOn)
      {
        actor->SetBackfaceProperty(GetBackFaceProperty());
      }
    }

    // Label the points.
    auto labelProperty = GetLabelProperty();
    if (singleObject)
    {
      labelProperty->SetFontSize(int(rendererSize / 36));
    }
    else
    {
      labelProperty->SetFontSize(int(rendererSize / 16));
    }

    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[names[idx]].data());

    vtkNew<vtkLightKit> lightKit;
    lightKit->AddLightsToRenderer(renderer);

    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.01, -0.05);
        tileActor->SetProperty(GetTileProperty());
        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();

    renderers[names[idx]] = renderer;
    renWin->AddRenderer(renderers[names[idx]]);

    ++idx;
  }

  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;
    renWin->AddRenderer(renderers[key]);
  }

#if VTK_HAS_COW
  vtkNew<vtkCameraOrientationWidget> camOrientManipulator;
#else
  vtkNew<vtkAxesActor> axes;
  vtkNew<vtkOrientationMarkerWidget> widget;
#endif

  if (singleObject)
  {
#if VTK_HAS_COW
    camOrientManipulator->SetParentRenderer(renderers[singleObjectName]);
    camOrientManipulator->SetInteractor(iRen);
    // Enable the widget.
    camOrientManipulator->On();
#else
    double rgba[4]{0.0, 0.0, 0.0, 0.0};
    colors->GetColor("Carrot", rgba);
    widget->SetOutlineColor(rgba[0], rgba[1], rgba[2]);
    widget->SetOrientationMarker(axes);
    widget->SetCurrentRenderer(renderers[singleObjectName]);
    widget->SetInteractor(iRen);
    widget->SetViewport(0.0, 0.0, 0.2, 0.2);
    widget->EnabledOn();
    widget->InteractiveOn();
#endif
  }

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

  return EXIT_SUCCESS;
}

namespace {

std::map<unsigned int, std::string> SpecifyObjects()
{
  return std::map<unsigned int, std::string>{
      {1, "VTK_VERTEX"},
      {2, "VTK_POLY_VERTEX"},
      {3, "VTK_LINE"},
      {4, "VTK_POLY_LINE"},
      {5, "VTK_TRIANGLE"},
      {6, "VTK_TRIANGLE_STRIP"},
      {7, "VTK_POLYGON"},
      {8, "VTK_PIXEL"},
      {9, "VTK_QUAD"},
      {10, "VTK_TETRA"},
      {11, "VTK_VOXEL"},
      {12, "VTK_HEXAHEDRON"},
      {13, "VTK_WEDGE"},
      {14, "VTK_PYRAMID"},
      {15, "VTK_PENTAGONAL_PRISM"},
      {16, "VTK_HEXAGONAL_PRISM"},
  };
}

cellMap GetUnstructuredGrids()
{
  return cellMap{
      {1, cellPair(MakeVertex(), {30, -30, 0.1})},
      {2, cellPair(MakePolyVertex(), {30, -30, 0.8})},
      {3, cellPair(MakeLine(), {30, -30, 0.4})},
      {4, cellPair(MakePolyLine(), {30, -30, 1.0})},
      {5, cellPair(MakeTriangle(), {30, -30, 0.7})},
      {6, cellPair(MakeTriangleStrip(), {30, -30, 1.1})},
      {7, cellPair(MakePolygon(), {0, -45, 1.0})},
      {8, cellPair(MakePixel(), {0, -45, 1.0})},
      {9, cellPair(MakeQuad(), {0, -45, 1.0})},
      {10, cellPair(MakeTetra(), {20, 20, 1.0})},
      {11, cellPair(MakeVoxel(), {-22.5, 15, 0.95})},
      {12, cellPair(MakeHexahedron(), {-22.5, 15, 0.95})},
      {13, cellPair(MakeWedge(), {-30, 15, 1.0})},
      {14, cellPair(MakePyramid(), {-60, 15, 1.0})},
      {15, cellPair(MakePentagonalPrism(), {-60, 10, 1.0})},
      {16, cellPair(MakeHexagonalPrism(), {-60, 15, 1.0})},
  };
}

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

vtkNew<vtkActor> MakeTile(double const bounds[], double const& expansionFactor,
                          double const& thicknessRatio, double shiftY)
{
  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] + shiftY, 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;
}

vtkNew<vtkTextProperty> GetTextProperty()
{
  vtkNew<vtkNamedColors> colors;

  vtkNew<vtkTextProperty> pty;
  pty->BoldOn();
  pty->SetJustificationToCentered();
  pty->SetColor(colors->GetColor3d("Black").GetData());
  return pty;
}

vtkNew<vtkTextProperty> GetLabelProperty()
{
  vtkNew<vtkNamedColors> colors;

  vtkNew<vtkTextProperty> pty;
  pty->BoldOn();
  pty->ShadowOn();
  pty->SetJustificationToCentered();
  pty->SetColor(colors->GetColor3d("DeepPink").GetData());
  return pty;
}

vtkNew<vtkProperty> GetBackFaceProperty()
{
  vtkNew<vtkNamedColors> colors;

  vtkNew<vtkProperty> pty;
  pty->SetAmbientColor(colors->GetColor3d("LightSalmon").GetData());
  pty->SetDiffuseColor(colors->GetColor3d("OrangeRed").GetData());
  pty->SetSpecularColor(colors->GetColor3d("White").GetData());
  pty->SetSpecular(0.2);
  pty->SetDiffuse(1.0);
  pty->SetAmbient(0.2);
  pty->SetSpecularPower(20.0);
  pty->SetOpacity(1.0);
  return pty;
}

vtkNew<vtkProperty> GetActorProperty()
{
  vtkNew<vtkNamedColors> colors;

  vtkNew<vtkProperty> pty;
  pty->SetAmbientColor(colors->GetColor3d("DarkSalmon").GetData());
  pty->SetDiffuseColor(colors->GetColor3d("Seashell").GetData());
  pty->SetSpecularColor(colors->GetColor3d("White").GetData());
  pty->SetSpecular(0.5);
  pty->SetDiffuse(0.7);
  pty->SetAmbient(0.5);
  pty->SetSpecularPower(20.0);
  pty->SetOpacity(0.8);
  pty->EdgeVisibilityOn();
  pty->SetLineWidth(3);
  return pty;
}

vtkNew<vtkProperty> GetPointActorProperty()
{
  vtkNew<vtkNamedColors> colors;

  vtkNew<vtkProperty> pty;
  pty->SetAmbientColor(colors->GetColor3d("Gold").GetData());
  pty->SetDiffuseColor(colors->GetColor3d("Yellow").GetData());
  pty->SetSpecularColor(colors->GetColor3d("White").GetData());
  pty->SetSpecular(0.5);
  pty->SetDiffuse(0.7);
  pty->SetAmbient(0.5);
  pty->SetSpecularPower(20.0);
  pty->SetOpacity(1.0);
  return pty;
}

vtkNew<vtkProperty> GetTileProperty()
{
  vtkNew<vtkNamedColors> colors;

  vtkNew<vtkProperty> pty;
  pty->SetAmbientColor(colors->GetColor3d("SteelBlue").GetData());
  pty->SetDiffuseColor(colors->GetColor3d("LightSteelBlue").GetData());
  pty->SetSpecularColor(colors->GetColor3d("White").GetData());
  pty->SetSpecular(0.5);
  pty->SetDiffuse(0.7);
  pty->SetAmbient(0.5);
  pty->SetSpecularPower(20.0);
  pty->SetOpacity(0.8);
  pty->EdgeVisibilityOn();
  pty->SetLineWidth(1);
  return pty;
}

} // namespace

CMakeLists.txt

cmake_minimum_required(VERSION 3.12 FATAL_ERROR)

project(LinearCellsDemo)

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

if (NOT VTK_FOUND)
  message(FATAL_ERROR "LinearCellsDemo: 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(LinearCellsDemo MACOSX_BUNDLE LinearCellsDemo.cxx )
  target_link_libraries(LinearCellsDemo PRIVATE ${VTK_LIBRARIES}
)
# vtk_module_autoinit is needed
vtk_module_autoinit(
  TARGETS LinearCellsDemo
  MODULES ${VTK_LIBRARIES}
)

Download and Build LinearCellsDemo

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

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

./LinearCellsDemo

WINDOWS USERS

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