1.3. Quick Start

In this chapter we go through the steps to create a simple program that uses VTK‑m. This “hello world” example presents only the bare minimum of features available. The remainder of this book documents dives into much greater detail.

We will call the example program we are building VTKmQuickStart. It will demonstrate reading data from a file, processing the data with a filter, and rendering an image of the data. Readers who are less interested in an explanation and are more interested in browsing some code can skip to Section 1.3.5 (The Full Example).

1.3.1. Initialize

The first step to using VTK‑m is to initialize the library. Although initializing VTK‑m is optional, it is recommend to allow VTK‑m to configure devices and logging. Initialization is done by calling the vtkm::cont::Initialize() function. The Initialize function is defined in the vtkm/cont/Initialize.h header file.

Initialize takes the argc and argv arguments that are passed to the main function of your program, find any command line arguments relevant to VTK‑m, and remove them from the list to make further command line argument processing easier.

Example 1.6 Initializing VTK‑m.
1int main(int argc, char* argv[])
2{
3  vtkm::cont::Initialize(argc, argv, vtkm::cont::InitializeOptions::AddHelp);

Initialize has many options to customize command line argument processing. See Chapter 2.3 (Initialization) for more details.

Did You Know?

Don’t have access to argc and argv? No problem. You can call vtkm::cont::Initialize() with no arguments.

1.3.2. Reading a File

VTK‑m comes with a simple I/O library that can read and write files in VTK legacy format. These files have a .vtk extension.

VTK legacy files can be read using the vtkm::io::VTKDataSetReader object, which is declared in the vtkm/io/VTKDataSetReader.h header file. The object is constructed with a string specifying the filename (which for this example we will get from the command line). The data is then read in by calling the vtkm::io::VTKDataSetReader::ReadDataSet() method.

Example 1.7 Reading data from a VTK legacy file.
1  vtkm::io::VTKDataSetReader reader(argv[1]);
2  vtkm::cont::DataSet inData = reader.ReadDataSet();

The ReadDataSet method returns the data in a vtkm::cont::DataSet object. The structure and features of a DataSet object is described in Chapter 2.4 (Data Sets). For the purposes of this quick start, we will treat DataSet as a mostly opaque object that gets passed to and from operations in VTK‑m.

More information about VTK‑m’s file readers and writers can be found in Chapter 2.5 (File I/O).

1.3.3. Running a Filter

Algorithms in VTK‑m are encapsulated in units called filters. A filter takes in a DataSet, processes it, and returns a new DataSet. The returned DataSet often, but not always, contains data inherited from the source data.

VTK‑m comes with many filters, which are documented in Chapter 2.7 (Provided Filters). For this example, we will demonstrate the use of the vtkm::filter::MeshQuality filter, which is defined in the vtkm/filter/MeshQuality.h header file. The MeshQuality filter will compute for each cell in the input data will compute a quantity representing some metric of the cell’s shape. Several metrics are available, and in this example we will find the area of each cell.

Like all filters, MeshQuality contains an Execute method that takes an input DataSet and produces an output DataSet. It also has several methods used to set up the parameters of the execution. Section 2.7.10.3 (Mesh Quality Metrics) provides details on all the options of MeshQuality. Suffice it to say that in this example we instruct the filter to find the area of each cell, which it will output to a field named area.

Example 1.8 Running a filter.
1  vtkm::filter::mesh_info::MeshQuality cellArea;
2  cellArea.SetMetric(vtkm::filter::mesh_info::CellMetric::Area);
3  vtkm::cont::DataSet outData = cellArea.Execute(inData);

1.3.4. Rendering an Image

Although it is possible to leverage external rendering systems, VTK‑m comes with its own self-contained image rendering algorithms. These rendering classes are completely implemented with the parallel features provided by VTK‑m, so using rendering in VTK‑m does not require any complex library dependencies.

Even a simple rendering scene requires setting up several parameters to establish what is to be featured in the image including what data should be rendered, how that data should be represented, where objects should be placed in space, and the qualities of the image to generate. Consequently, setting up rendering in VTK‑m involves many steps. Chapter 2.8 (Rendering) goes into much detail on the ways in which a rendering scene is specified. For now, we just briefly present some boilerplate to achieve a simple rendering.

Example 1.9 Rendering data.
 1  vtkm::rendering::Actor actor(
 2    outData.GetCellSet(), outData.GetCoordinateSystem(), outData.GetField("area"));
 3
 4  vtkm::rendering::Scene scene;
 5  scene.AddActor(actor);
 6
 7  vtkm::rendering::MapperRayTracer mapper;
 8
 9  vtkm::rendering::CanvasRayTracer canvas(1280, 1024);
10
11  vtkm::rendering::View3D view(scene, mapper, canvas);
12
13  view.Paint();
14
15  view.SaveAs("image.png");

The first step in setting up a render is to create a scene. A scene comprises some number of actors, which represent some data to be rendered in some location in space. In our case we only have one DataSet to render, so we simply create a single actor and add it to a scene as shown in Example 1.9 lines 1 – 5.

The second step in setting up a render is to create a view. The view comprises the aforementioned scene, a mapper, which describes how the data are to be rendered, and a canvas, which holds the image buffer and other rendering context. The view is created in Example 1.9, line 11. The image generation is then performed by calling vtkm::rendering::View::Paint() on the view object (Example 1.9, line 13). However, the rendering done by VTK‑m’s rendering classes is performed offscreen, which means that the result does not appear on your computer’s monitor. The easiest way to see the image is to save it to an image file using the vtkm::rendering::View::SaveAs() method (Example 1.9, line 15).

1.3.5. The Full Example

Putting together the examples from the previous sections, here is a complete program for reading, processing, and rendering data with VTK‑m.

Example 1.10 Simple example of using VTK‑m.
 1#include <vtkm/cont/Initialize.h>
 2
 3#include <vtkm/io/VTKDataSetReader.h>
 4
 5#include <vtkm/filter/mesh_info/MeshQuality.h>
 6
 7#include <vtkm/rendering/Actor.h>
 8#include <vtkm/rendering/CanvasRayTracer.h>
 9#include <vtkm/rendering/MapperRayTracer.h>
10#include <vtkm/rendering/Scene.h>
11#include <vtkm/rendering/View3D.h>
12
13int main(int argc, char* argv[])
14{
15  vtkm::cont::Initialize(argc, argv, vtkm::cont::InitializeOptions::AddHelp);
16
17  if (argc != 2)
18  {
19    std::cerr << "USAGE: " << argv[0] << " <file.vtk>" << std::endl;
20    return 1;
21  }
22
23  // Read in a file specified in the first command line argument.
24  vtkm::io::VTKDataSetReader reader(argv[1]);
25  vtkm::cont::DataSet inData = reader.ReadDataSet();
26
27  // Run the data through the elevation filter.
28  vtkm::filter::mesh_info::MeshQuality cellArea;
29  cellArea.SetMetric(vtkm::filter::mesh_info::CellMetric::Area);
30  vtkm::cont::DataSet outData = cellArea.Execute(inData);
31
32  // Render an image and write it out to a file.
33  vtkm::rendering::Actor actor(
34    outData.GetCellSet(), outData.GetCoordinateSystem(), outData.GetField("area"));
35
36  vtkm::rendering::Scene scene;
37  scene.AddActor(actor);
38
39  vtkm::rendering::MapperRayTracer mapper;
40
41  vtkm::rendering::CanvasRayTracer canvas(1280, 1024);
42
43  vtkm::rendering::View3D view(scene, mapper, canvas);
44
45  view.Paint();
46
47  view.SaveAs("image.png");
48
49  return 0;
50}

1.3.6. Build Configuration

Now that we have the program listed in Example 1.10, we still need to compile it with the appropriate compilers and flags. By far the easiest way to compile VTK‑m code is to use CMake. CMake commands that can be used to link code to VTK‑m are discussed in Section 1.2.4 (Linking to VTK‑m). The following example provides a minimal CMakeLists.txt required to build this program.

Example 1.11 CMakeLists.txt to build a program using VTK‑m.
1cmake_minimum_required(VERSION 3.13)
2project(VTKmQuickStart CXX)
3
4find_package(VTKm REQUIRED)
5
6add_executable(VTKmQuickStart VTKmQuickStart.cxx)
7target_link_libraries(VTKmQuickStart vtkm::filter vtkm::rendering)

The first two lines contain boilerplate for any CMakeLists.txt file. They all should declare the minimum CMake version required (for backward compatibility) and have a project() command to declare which languages are used.

The remainder of the commands find the VTK‑m library, declare the program begin compiled, and link the program to the VTK‑m library. These steps are described in detail in Section 1.2.4 (Linking to VTK‑m).