Continue transfer of Users' Guide text

These changes complete the using part of the guide.
This commit is contained in:
Kenneth Moreland 2023-07-27 14:07:19 -06:00
parent 7302372b48
commit 5b8c282e9f
220 changed files with 8896 additions and 948 deletions

@ -10,7 +10,11 @@
#ifndef @EXPORT_MACRO_NAME@_EXPORT_H
#define @EXPORT_MACRO_NAME@_EXPORT_H
#if defined(_MSC_VER)
#if defined(VTKM_DOXYGEN_ONLY)
# define @EXPORT_MACRO_NAME@_EXPORT_DEFINE
# define @EXPORT_MACRO_NAME@_IMPORT_DEFINE
# define @EXPORT_MACRO_NAME@_NO_EXPORT_DEFINE
#elif defined(_MSC_VER)
# if @EXPORT_IS_BUILT_STATIC@
/* This is a static component and has no need for exports
elf based static libraries are able to have hidden/default visibility

@ -132,6 +132,7 @@ INPUT = @VTKm_SOURCE_DIR@/README.md
INPUT += @VTKm_SOURCE_DIR@/CONTRIBUTING.md
INPUT += @VTKm_SOURCE_DIR@/docs/CodingConventions.md
INPUT += @VTKm_SOURCE_DIR@/vtkm
INPUT += @VTKm_BINARY_DIR@/include
USE_MDFILE_AS_MAINPAGE = README.md
@ -328,13 +329,16 @@ PERLMOD_MAKEVAR_PREFIX =
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
# Turning macro expansion on is required to work around issue with breathe
# (for Sphinx documentation) parsing function modifiers.
# https://github.com/breathe-doc/breathe/issues/905
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH = @VTKm_SOURCE_DIR@ @VTKm_BINARY_DIR@
INCLUDE_PATH = @VTKm_SOURCE_DIR@ @VTKm_BINARY_DIR@/include
INCLUDE_FILE_PATTERNS =

@ -120,7 +120,7 @@ A ``Vec`` also supports basic arithmetic operators so that it can be used much l
.. load-example:: SimpleVectorTypes
:file: GuideExampleCoreDataTypes.cxx
:caption: Simple use of ``Vec`` objects.}
:caption: Simple use of ``Vec`` objects.
You can also specify the precision for each of these vector types by appending the bit size of each component.
For example, :type:`vtkm::Vec3f_32` and :type:`vtkm::Vec3f_64` represent 3-component floating point vectors with each component being 32 bits and 64 bits respectively.

@ -0,0 +1,21 @@
.. DO NOT EDIT!
.. Created by GuideExampleColorTables test.
.. |Black---Blue---White| image:: images/color-tables/Black---Blue---White.png
.. |Black-Body-Radiation| image:: images/color-tables/Black-Body-Radiation.png
.. |Blue---Green---Orange| image:: images/color-tables/Blue---Green---Orange.png
.. |Blue-to-Orange| image:: images/color-tables/Blue-to-Orange.png
.. |Cold-and-Hot| image:: images/color-tables/Cold-and-Hot.png
.. |Cool-to-Warm| image:: images/color-tables/Cool-to-Warm.png
.. |Cool-to-Warm-Extended| image:: images/color-tables/Cool-to-Warm-Extended.png
.. |Default| image:: images/color-tables/Default.png
.. |Gray-to-Red| image:: images/color-tables/Gray-to-Red.png
.. |Green| image:: images/color-tables/Green.png
.. |Inferno| image:: images/color-tables/Inferno.png
.. |Jet| image:: images/color-tables/Jet.png
.. |Plasma| image:: images/color-tables/Plasma.png
.. |Rainbow-Desaturated| image:: images/color-tables/Rainbow-Desaturated.png
.. |Rainbow-Uniform| image:: images/color-tables/Rainbow-Uniform.png
.. |Viridis| image:: images/color-tables/Viridis.png
.. |X-Ray| image:: images/color-tables/X-Ray.png
.. |Yellow---Gray---Blue| image:: images/color-tables/Yellow---Gray---Blue.png

@ -0,0 +1,592 @@
==============================
Data Sets
==============================
.. index:: data set
A *data set*, implemented with the :class:`vtkm::cont::DataSet` class,
contains and manages the geometric data structures that |VTKm| operates on.
.. index::
single: cell set
single: field
single: coordinate system
.. doxygenclass:: vtkm::cont::DataSet
In addition to the base :class:`vtkm::cont::DataSet`, |VTKm| provides :class:`vtkm::cont::PartitionedDataSet` to represent data partitioned into multiple domains.
A :class:`vtkm::cont::PartitionedDataSet` is implemented as a collection of :class:`vtkm::cont::DataSet` objects.
Partitioned data sets are described later in :secref:`dataset:Partitioned Data Sets`.
------------------------------
Building Data Sets
------------------------------
.. index:: data set ; building
Before we go into detail on the cell sets, fields, and coordinate systems that make up a data set in |VTKm|, let us first discuss how to build a data set.
One simple way to build a data set is to load data from a file using the `vtkm::io` module.
Reading files is discussed in detail in Chapter~\ref{chap:FileIO}.
.. todo:: Add previous reference.
This section describes building data sets of different types using a set of
classes named `DataSetBuilder*`, which provide a convenience layer
on top of :class:`vtkm::cont::DataSet` to make it easier to create data sets.
.. didyouknow::
To simplify the introduction of :class:`vtkm::cont::DataSet` objects, this section uses the simplest mechanisms.
In many cases this involves loading data in a `std::vector` and passing that to |VTKm|, which usually causes the data to be copied.
This is not the most efficient method to load data into |VTKm|.
Although it is sufficient for small data or data that come from a "slow" source, such as a file, it might be a bottleneck for large data generated by another library.
It is possible to adapt |VTKm|'s :class:`vtkm::cont::DataSet` to externally defined data.
This is done by wrapping existing data into what is called `ArrayHandle`, but this is a more advanced topic that will not be addressed in this chapter.
`ArrayHandle` objects are introduced in Chapter \ref{chap:BasicArrayHandles} and more adaptive techniques are described in later chapters.
.. todo:: Add previous reference.
Creating Uniform Grids
==============================
.. index::
single: uniform grid
single: regular grid
single: image
Uniform grids are meshes that have a regular array structure with points uniformly spaced parallel to the axes.
Uniform grids are also sometimes called regular grids or images.
The :class:`vtkm::cont::DataSetBuilderUniform` class can be used to easily create 2- or 3-dimensional uniform grids.
:class:`vtkm::cont::DataSetBuilderUniform` has several versions of a method named :func:`vtkm::cont::DataSetBuilderUniform::Create` that takes the number of points in each dimension, the origin, and the spacing.
The origin is the location of the first point of the data (in the lower left corner), and the spacing is the distance between points in the x, y, and z directions.
.. doxygenclass:: vtkm::cont::DataSetBuilderUniform
:members:
The following example creates a :class:`vtkm::cont::DataSet` containing a uniform grid of :math:`101 \times 101 \times 26` points.
.. load-example:: CreateUniformGrid
:file: GuideExampleDataSetCreation.cxx
:caption: Creating a uniform grid.}{.cxx}
If not specified, the origin will be at the coordinates :math:`(0,0,0)` and the spacing will be :math:`1` in each direction.
Thus, in the previous example the width, height, and depth of the mesh in physical space will be :math:`100`, :math:`100`, and :math`25`, respectively, and the mesh will be centered at :math:`(50, 50, 12.5)`.
Let us say we actually want a mesh of the same dimensions, but we want the :math:`z` direction to be stretched out so that the mesh will be the same size in each direction, and we want the mesh centered at the origin.
.. load-example:: CreateUniformGridCustomOriginSpacing
:file: GuideExampleDataSetCreation.cxx
:caption: Creating a uniform grid with custom origin and spacing.
Creating Rectilinear Grids
==============================
.. index:: rectilinear grid
A rectilinear grid is similar to a uniform grid except that a rectilinear grid can adjust the spacing between adjacent grid points.
This allows the rectilinear grid to have tighter sampling in some areas of space, but the points are still constrained to be aligned with the axes and each other.
The irregular spacing of a rectilinear grid is specified by providing a separate array each for the x, y, and z coordinates.
The :class:`vtkm::cont::DataSetBuilderRectilinear` class can be used to easily create
2- or 3-dimensional rectilinear grids.
:class:`vtkm::cont::DataSetBuilderRectilinear` has several versions of a method
named :func:`vtkm::cont::DataSetBuilderRectilinear::Create` that takes these coordinate arrays and builds a
:class:`vtkm::cont::DataSet` out of them. The arrays can be supplied as either
standard C arrays or as `std::vector` objects, in which case the
data in the arrays are copied into the :class:`vtkm::cont::DataSet`. These
arrays can also be passed as :class:`vtkm::cont::ArrayHandle` objects (introduced later in this book), in which
case the data are shallow copied.
.. doxygenclass:: vtkm::cont::DataSetBuilderRectilinear
:members:
The following example creates a :class:`vtkm::cont::DataSet` containing a rectilinear
grid with :math:`201 \times 201 \times 101` points with different irregular
spacing along each axis.
.. load-example:: CreateRectilinearGrid
:file: GuideExampleDataSetCreation.cxx
:caption: Creating a rectilinear grid.
Creating Explicit Meshes
==============================
.. index::
single: explicit mesh
single: unstructured grid
An explicit mesh is an arbitrary collection of cells with arbitrary connections.
It can have multiple different types of cells.
Explicit meshes are also known as unstructured grids.
Explicit meshes can contain cells of different shapes.
The shapes that |VTKm| currently supports are listed in :numref:`fig:CreateExplicitMeshesCellShapes`.
Each shape is identified using either a numeric identifier, provided by |VTKm| with identifiers of the form ``vtkm::CELL_SHAPE_*`` or special tag structures of the form ``vtkm::CellSetTag*``.
Cell shapes are discussed in detail in ???.
.. todo:: Add cell shape reference above.
.. figure:: images/CellConnections.png
:width: 100%
:name: fig:CreateExplicitMeshesCellShapes
Basic Cell Shapes.
..
.. |CellConnectionsVertex| image:: images/CellConnectionsVertex.png
.. |CellConnectionsLine| image:: images/CellConnectionsLine.png
.. |CellConnectionsPolyLine| image:: images/CellConnectionsPolyLine.png
.. |CellConnectionsTriangle| image:: images/CellConnectionsTriangle.png
.. |CellConnectionsPolygon| image:: images/CellConnectionsPolygon.png
.. |CellConnectionsQuadrilateral| image:: images/CellConnectionsQuadrilateral.png
.. |CellConnectionsTetrahedron| image:: images/CellConnectionsTetrahedron.png
.. |CellConnectionsHexahedron| image:: images/CellConnectionsHexahedron.png
.. |CellConnectionsWedge| image:: images/CellConnectionsWedge.png
.. |CellConnectionsPyramid| image:: images/CellConnectionsPyramid.png
.. table:: Basic Cell Shapes
:name: ExplicitCellShapes
:width: 100%
+----------------------------------------------+----------------------------------------------+----------------------------------------------+
| :enumerator:`vtkm::CELL_SHAPE_VERTEX` | :enumerator:`vtkm::CELL_SHAPE_Line` | :enumerator:`vtkm::CELL_SHAPE_POLY_LINE` |
| :struct:`vtkm::CellShapeTagVertex` | :struct:`vtkm::CellShapeTagLine` | :struct:`vtkm::CellShapeTagPolyLine` |
| |CellConnectionsVertex| | |CellConnectionsLine| | |CellConnectionsPolyLine| |
+----------------------------------------------+----------------------------------------------+----------------------------------------------+
| :enumerator:`vtkm::CELL_SHAPE_TRIANGLE` | :enumerator:`vtkm::CELL_SHAPE_POLYGON` | :enumerator:`vtkm::CELL_SHAPE_QUADRILATERAL` |
| :struct:`vtkm::CellShapeTagTriangle` | :struct:`vtkm::CellShapeTagPolygon` | :struct:`vtkm::CellShapeTagQuadrilateral` |
| |CellConnectionsTriangle| | |CellConnectionsPolygon| | |CellConnectionsQuadrilateral| |
+----------------------------------------------+----------------------------------------------+----------------------------------------------+
| :enumerator:`vtkm::CELL_SHAPE_TETRAHEDRON` | :enumerator:`vtkm::CELL_SHAPE_HEXAHEDRON` | :enumerator:`vtkm::CELL_SHAPE_WEDGE` |
| :struct:`vtkm::CellShapeTagTetrahedron` | :struct:`vtkm::CellShapeTagHexahedron` | :struct:`vtkm::CellShapeTagWedge` |
| |CellConnectionsTetrahedron| | |CellConnectionsHexahedron| | |CellConnectionsWedge| |
+----------------------------------------------+----------------------------------------------+----------------------------------------------+
| | :enumerator:`vtkm::CELL_SHAPE_PYRAMID` | |
| | :struct:`vtkm::CellShapeTagPyramid` | |
| | |CellConnectionsPyramid| | |
+----------------------------------------------+----------------------------------------------+----------------------------------------------+
.. figure:: images/ExplicitCellConnections.png
:width: 100%
:name: fig:ExplicitMesh
An example explicit mesh.
The cells of an explicit mesh are defined with the following 3 arrays, which are depicted graphically in :numref:`fig:ExplicitMesh`.
.. index:: explicit mesh ; shapes
Shapes
An array of ids identifying the shape of the cell.
Each value is a :type:`vtkm::UInt8` and should be set to one of the ``vtkm::CELL_SHAPE_*`` constants.
The shapes and their identifiers are shown in :numref:`fig:CreateExplicitMeshesCellShapes`.
The size of this array is equal to the number of cells in the set.
.. index:: explicit mesh ; connectivity
Connectivity
An array that lists all the points that comprise each cell.
Each entry in the array is a :type:`vtkm::Id` giving the point id associated with a vertex of a cell.
The points for each cell are given in a prescribed order for each shape, which is also shown in :numref:`fig:CreateExplicitMeshesCellShapes`.
The point indices are stored consecutively from the first cell to the last.
.. index:: explicit mesh ; offsets
Offsets
An array of :type:`vtkm::Id`'s pointing to the index in the connectivity array where the points for a particular cell starts.
The size of this array is equal to the number of cells in the set plus 1.
The first entry is expected to be 0 (since the connectivity of the first cell is at the start of the connectivity array).
The last entry, which does not correspond to any cell, should be the size of the connectivity array.
One important item that is missing from this list of arrays is a count of the number of indices associated with each cell.
This is not explicitly represented in |VTKm|'s mesh structure because it can be implicitly derived from the offsets array by subtracting consecutive entries.
However, it is usually the case when building an explicit mesh that you will have an array of these counts rather than the offsets.
It is for this reason that |VTKm| contains mechanisms to build an explicit data set with a "num indices" arrays rather than an offsets array.
The :class:`vtkm::cont::DataSetBuilderExplicit` class can be used to create data sets with explicit meshes.
:class:`vtkm::cont::DataSetBuilderExplicit` has several versions of a method named :func:`vtkm::cont::DataSetBuilderExplicit::Create`.
Generally, these methods take the shapes, number of indices, and connectivity arrays as well as an array of point coordinates.
.. doxygenclass:: vtkm::cont::DataSetBuilderExplicit
:members:
The following example creates a mesh like the one shown in
:numref:`fig:ExplicitMesh`.
.. load-example:: CreateExplicitGrid
:file: GuideExampleDataSetCreation.cxx
:caption: Creating an explicit mesh with :class:`vtkm::cont::DataSetBuilderExplicit`.
Often it is awkward to build your own arrays and then pass them to :class:`vtkm::cont::DataSetBuilderExplicit`.
There also exists an alternate builder class named :class:`vtkm::cont::DataSetBuilderExplicitIterative` that allows you to specify each cell and point one at a time rather than all at once.
This is done by calling one of the versions of :func:`vtkm::cont::DataSetBuilderExplicitIterative::AddPoint` and one of the versions of :func:`vtkm::cont::DataSetBuilderExplicitIterative::AddCell` for each point and cell, respectively.
.. doxygenclass:: vtkm::cont::DataSetBuilderExplicitIterative
:members:
The next example also builds the mesh shown in :numref:`fig:ExplicitMesh` except this time using :class:`vtkm::cont::DataSetBuilderExplicitIterative`.
.. load-example:: CreateExplicitGridIterative
:file: GuideExampleDataSetCreation.cxx
:caption: Creating an explicit mesh with :class:`vtkm::cont::DataSetBuilderExplicitIterative`.
Add Fields
==============================
In addition to creating the geometric structure of a data set, it is usually important to add fields to the data.
Fields describe numerical data associated with the topological elements in a cell.
They often represent a physical quantity (such as temperature, mass, or volume fraction) but can also represent other information (such as indices or classifications).
The easiest way to define fields in a data set is to use the :func:`vtkm::cont::DataSet::AddPointField` and :func:`vtkm::cont::DataSet::AddCellField` methods.
Each of these methods take a requisite field name and the array with with field data.
Both :func:`vtkm::cont::DataSet::AddPointField` and :func:`vtkm::cont::DataSet::AddCellField` are overloaded to accept arrays of data in different structures.
Field arrays can be passed as standard C arrays or as ``std::vector``'s, in which case the data are copied.
Field arrays can also be passed in a ``ArrayHandle`` (introduced later in this book), in which case the data are not copied.
.. doxygenfunction:: vtkm::cont::DataSet::AddPointField(const std::string&, const vtkm::cont::UnknownArrayHandle&)
.. doxygenfunction:: vtkm::cont::DataSet::AddPointField(const std::string&, const std::vector<T>&)
.. doxygenfunction:: vtkm::cont::DataSet::AddPointField(const std::string&, const T*, const vtkm::Id&)
.. doxygenfunction:: vtkm::cont::DataSet::AddCellField(const std::string&, const vtkm::cont::UnknownArrayHandle&)
.. doxygenfunction:: vtkm::cont::DataSet::AddCellField(const std::string&, const std::vector<T>&)
.. doxygenfunction:: vtkm::cont::DataSet::AddCellField(const std::string&, const T*, const vtkm::Id&)
The following (somewhat contrived) example defines fields for a uniform grid that identify which points and cells are on the boundary of the mesh.
.. load-example:: AddFieldData
:file: GuideExampleDataSetCreation.cxx
:caption: Adding fields to a :class:`vtkm::cont::DataSet`.
------------------------------
Cell Sets
------------------------------
.. index:: cell set
.. index:: data set ; cell set
.. index::
triple: cell; shape; point
triple: cell; shape; edge
triple: cell; shape; face
A cell set determines the topological structure of the data in a data set.
.. doxygenclass:: vtkm::cont::CellSet
:members:
3D cells are made up of *points*, *edges*, and *faces*.
(2D cells have only points and edges, and 1D cells have only points.)
:numref:`fig:CellTopology` shows the relationship between a cell's shape and these topological elements.
The arrangement of these points, edges, and faces is defined by the *shape* of the cell, which prescribes a specific ordering of each.
The basic cell shapes provided by |VTKm| are discussed in detail in Section~\ref{sec:CellShapeTagsIds} starting on page~\pageref{sec:CellShapeTagsIds}.
.. todo:: Add cell shape reference above.
.. figure:: images/CellConstituents.png
:width: 50%
:name: fig:CellTopology
The relationship between a cell shape and its topological elements (points, edges, and faces).
There are multiple ways to express the connections of a cell set, each with
different benefits and restrictions. These different cell set types are
managed by different cell set classes in |VTKm|. All |VTKm| cell set classes
inherit from :class:`vtkm::cont::CellSet`. The two basic types of cell sets are
structured and explicit, and there are several variations of these types.
Structured Cell Sets
==============================
.. index::
single: cell set; structured
single: structured cell set
.. doxygenclass:: vtkm::cont::CellSetStructured
:members:
The number of points in a :class:`vtkm::cont::CellSetStructured` is implicitly :math:`i \times j \times k` and the number of cells is implicitly :math:`(i-1) \times (j-1) \times (k-1)` (for 3D grids).
:numref:`fig:CellSetStructured` demonstrates this arrangement.
.. figure:: images/StructuredCellSet.png
:width: 100%
:name: fig:CellSetStructured
The arrangement of points and cells in a 3D structured grid.
The big advantage of using :class:`vtkm::cont::CellSetStructured` to define a cell set is that it is very space efficient because the entire topology can be defined by the three integers specifying the dimensions.
Also, algorithms can be optimized for :class:`vtkm::cont::CellSetStructured`'s regular nature.
However, :class:`vtkm::cont::CellSetStructured`'s strictly regular grid also limits its applicability.
A structured cell set can only be a dense grid of lines, quadrilaterals, or hexahedra.
It cannot represent irregular data well.
Many data models in other software packages, such as the one for VTK, make a distinction between uniform, rectilinear, and curvilinear grids.
|VTKm|'s cell sets do not.
All three of these grid types are represented by :class:`vtkm::cont::CellSetStructured`.
This is because in a |VTKm| data set the cell set and the coordinate system are defined independently and used interchangeably.
A structured cell set with uniform point coordinates makes a uniform grid.
A structured cell set with point coordinates defined irregularly along coordinate axes makes a rectilinear grid.
And a structured cell set with arbitrary point coordinates makes a curvilinear grid.
The point coordinates are defined by the data set's coordinate system, which is discussed in :secref:`dataset:Coordinate Systems`.
Explicit Cell Sets
==============================
.. index::
single: cell set; explicit
single: explicit cell set
.. doxygenclass:: vtkm::cont::CellSetExplicit
:members:
The types of cell sets are listed in :numref:`fig:ExplicitCellSetShapes`.
.. figure:: images/CellConnections.png
:width: 100%
:name: fig:ExplicitCellSetShapes
Basic Cell Shapes in a :class:`vtkm::cont::CellSetExplicit`.
An explicit cell set is defined with a minimum of three arrays.
The first array identifies the shape of each cell.
(Identifiers for cell shapes are shown in :numref:`fig:ExplicitCellSetShapes`.)
The second array has a sequence of point indices that make up each cell.
The third array identifies an offset into the second array where the point indices for each cell is found plus an extra entry at the end set to the size of the second array.
:numref:`fig:CellSetExplicit` shows a simple example of an explicit cell set.
.. figure:: images/ExplicitCellConnections.png
:width: 100%
:name: fig:CellSetExplicit
Example of cells in a :class:`vtkm::cont::CellSetExplicit` and the arrays that define them.
An explicit cell set can also identify the number of indices defined for each cell by subtracting consecutive entries in the offsets array.
It is often the case when creating a :class:`vtkm::cont::CellSetExplicit` that you have an array containing the number of indices rather than the offsets.
Such an array can be converted to an offsets array that can be used with :class:`vtkm::cont::CellSetExplicit` by using the :func:`vtkm::cont::ConvertNumComponentsToOffsets` convenience function.
.. doxygenfunction:: vtkm::cont::ConvertNumComponentsToOffsets(const vtkm::cont::UnknownArrayHandle&, vtkm::cont::ArrayHandle<vtkm::Id>&, vtkm::Id&, vtkm::cont::DeviceAdapterId)
:class:`vtkm::cont::CellSetExplicit` is a powerful representation for a cell set
because it can represent an arbitrary collection of cells. However, because
all connections must be explicitly defined,
:class:`vtkm::cont::CellSetExplicit` requires a significant amount of memory to
represent the topology.
.. index::
single: cell set; single type
single: explicit cell set; single type
single: single type cell set
An important specialization of an explicit cell set is
:class:`vtkm::cont::CellSetSingleType`.
.. doxygenclass:: vtkm::cont::CellSetSingleType
:members:
Cell Set Permutations
==============================
.. index::
single: cell set; permutation
single: permutation cell set
To rearrange, and possibly subsample, cells in a ``CellSet``, use :type:`vtkm::cont::CellSetPermutation` to define a new set without copying.
.. doxygenclass:: vtkm::cont::CellSetPermutation
:members:
.. didyouknow::
Although :class:`vtkm::cont::CellSetPermutation` can mask cells, it cannot mask points.
All points from the original cell set are available in the permuted cell set regardless of whether they are used.
The following example uses :class:`vtkm::cont::CellSetPermutation` with a counting array to expose every tenth cell.
This provides a simple way to subsample a data set.
.. load-example:: CreateCellSetPermutation
:file: GuideExampleDataSetCreation.cxx
:caption: Subsampling a data set with :class:`vtkm::cont::CellSetPermutation`.
Cell Set Extrude
==============================
.. doxygenclass:: vtkm::cont::CellSetExtrude
:members:
.. figure:: images/ExtrudedCellSet.png
:width: 100%
:name: fig:CellSetExtruded
An example of an extruded wedge from XZ-plane coordinates.
Six wedges are extracted from three XZ-plane points.
The extruded mesh is advantageous because it is represented on-the-fly as required, so no additional memory is required.
In contrast other forms of cell sets, such as :class:`vtkm::cont::CellSetExplicit`, need to be explicitly constructed by replicating the vertices and cells.
:numref:`fig:CellSetExtruded` shows an example of six wedges extruded from three 2-dimensional coordinates.
Unknown Cell Sets
==============================
Each of the aforementioned cell set types are represented by a different class.
A :class:`vtkm::cont::DataSet` object must hold one of these cell set objects that represent the cell structure.
The actual object used is not determined until run time.
The :class:`vtkm::cont::DataSet` object manages the cell set object with :class:`vtkm::cont::UnknownCellSet`.
When you call :func:`vtkm::cont::DataSet::GetCellSet`, it returns a :class:`vtkm::cont::UnknownCellSet`.
The :class:`vtkm::cont::UnknownCellSet` object provides mechanisms to query the cell set, identify its type, and cast it to one of the concrete ``CellSet`` types.
See Chapter \ref{chap:UnknownCellSet} for details on working with :class:`vtkm::cont::UnknownCellSet`.
.. todo:: Add previous reference to UnknownCellSet chapter.
------------------------------
Fields
------------------------------
.. index::
single: field
single: data set; field
A field on a data set provides a value on every point in space on the mesh.
Fields are often used to describe physical properties such as pressure, temperature, mass, velocity, and much more.
Fields are represented in a |VTKm| data set as an array where each value is associated with a particular element type of a mesh (such as points or cells).
This association of field values to mesh elements and the structure of the cell set determines how the field is interpolated throughout the space of the mesh.
Fields are manged by the :class:`vtkm::cont::Field` class.
.. doxygenclass:: vtkm::cont::Field
Fields are identified by a simple name string.
.. doxygenfunction:: vtkm::cont::Field::GetName
The :class:`vtkm::cont::Field` object internally holds a reference to an array in a type-agnostic way.
Filters and other |VTKm| units will determine the type of the array and pull it out of the :class:`vtkm::cont::Field`.
.. doxygenfunction:: vtkm::cont::Field::GetData() const
The field data is associated with a particular type of element of a mesh such as points, cells, or the whole mesh.
.. doxygenfunction:: vtkm::cont::Field::GetAssociation
Associations are identified by the :enum:`vtkm::cont::Field::Association` enumeration.
.. doxygenenum:: vtkm::cont::Field::Association
The :class:`vtkm::cont::Field` class also has several convenience methods for querying the association.
.. doxygenfunction:: vtkm::cont::Field::IsPointField
.. doxygenfunction:: vtkm::cont::Field::IsCellField
.. doxygenfunction:: vtkm::cont::Field::IsWholeDataSetField
.. doxygenfunction:: vtkm::cont::Field::IsPartitionsField
.. doxygenfunction:: vtkm::cont::Field::IsGlobalField
.. index:: double: range; field
:class:`vtkm::cont::Field` has a convenience method named :func:`vtkm::cont::Field::GetRange` that finds the range of values stored in the field array.
.. doxygenfunction:: vtkm::cont::Field::GetRange() const
Details on how to get data from a :class:`vtkm::cont::ArrayHandle` them is given in Chapter \ref{chap:AccessingAllocatingArrays}.
.. todo:: Fix above reference to array handle chapter.
------------------------------
Coordinate Systems
------------------------------
.. index::
single: coordinate system
single: data set; coordinate system
A coordinate system determines the location of a mesh's elements in space.
The spatial location is described by providing a 3D vector at each point that gives the coordinates there.
The point coordinates can then be interpolated throughout the mesh.
.. doxygenclass:: vtkm::cont::CoordinateSystem
In addition to all the methods provided by the :class:`vtkm::cont::Field` superclass, the :class:`vtkm::cont::CoordinateSystem` also provides a :func:`vtkm::cont::CoordinateSystem::GetBounds` convenience method that returns a :class:`vtkm::Bounds` object giving the spatial bounds of the coordinate system.
.. doxygenfunction:: vtkm::cont::CoordinateSystem::GetBounds
It is typical for a :class:`vtkm::cont::DataSet` to have one coordinate system defined, but it is possible to define multiple coordinate systems.
This is helpful when there are multiple ways to express coordinates.
For example, positions in geographic may be expressed as Cartesian coordinates or as latitude-longitude coordinates.
Both are valid and useful in different ways.
It is also valid to have a :class:`vtkm::cont::DataSet` with no coordinate system.
This is useful when the structure is not rooted in physical space.
For example, if the cell set is representing a graph structure, there might not be any physical space that has meaning for the graph.
------------------------------
Partitioned Data Sets
------------------------------
.. index::
single: partitioned data set
single: data set; partitioned
.. doxygenclass:: vtkm::cont::PartitionedDataSet
:members:
The following example creates a :class:`vtkm::cont::PartitionedDataSet` containing two uniform grid data sets.
.. load-example:: CreatePartitionedDataSet
:file: GuideExampleDataSetCreation.cxx
:caption: Creating a :class:`vtkm::cont::PartitionedDataSet`.
It is always possible to retrieve the independent blocks in a :class:`vtkm::cont::PartitionedDataSet`, from which you can iterate and get information about the data.
However, |VTKm| provides several helper functions to collect metadata information about the collection as a whole.
.. doxygenfunction:: vtkm::cont::BoundsCompute(const vtkm::cont::DataSet&, vtkm::Id)
.. doxygenfunction:: vtkm::cont::BoundsCompute(const vtkm::cont::PartitionedDataSet&, vtkm::Id)
.. doxygenfunction:: vtkm::cont::BoundsCompute(const vtkm::cont::DataSet&, const std::string&)
.. doxygenfunction:: vtkm::cont::BoundsCompute(const vtkm::cont::PartitionedDataSet&, const std::string&)
.. doxygenfunction:: vtkm::cont::BoundsGlobalCompute(const vtkm::cont::DataSet&, vtkm::Id)
.. doxygenfunction:: vtkm::cont::BoundsGlobalCompute(const vtkm::cont::PartitionedDataSet&, vtkm::Id)
.. doxygenfunction:: vtkm::cont::BoundsGlobalCompute(const vtkm::cont::DataSet&, const std::string&)
.. doxygenfunction:: vtkm::cont::BoundsGlobalCompute(const vtkm::cont::PartitionedDataSet&, const std::string&)
.. doxygenfunction:: vtkm::cont::FieldRangeCompute(const vtkm::cont::DataSet&, const std::string&, vtkm::cont::Field::Association)
.. doxygenfunction:: vtkm::cont::FieldRangeCompute(const vtkm::cont::PartitionedDataSet&, const std::string&, vtkm::cont::Field::Association)
.. doxygenfunction:: vtkm::cont::FieldRangeGlobalCompute(const vtkm::cont::DataSet&, const std::string&, vtkm::cont::Field::Association)
.. doxygenfunction:: vtkm::cont::FieldRangeGlobalCompute(const vtkm::cont::PartitionedDataSet&, const std::string&, vtkm::cont::Field::Association)
The following example illustrates a spatial bounds query and a field range query on a :class:`vtkm::cont::PartitionedDataSet`.
.. load-example:: QueryPartitionedDataSet
:file: GuideExampleDataSetCreation.cxx
:caption: Queries on a :class:`vtkm::cont::PartitionedDataSet`.
.. didyouknow::
The aforementioned functions for querying a :class:`vtkm::cont::PartitionedDataSet` object also work on :class:`vtkm::cont::DataSet` objects.
This is particularly useful with the :func:`vtkm::cont::BoundsGlobalCompute` and :func:`vtkm::cont::FieldRangeGlobalCompute` functions to manage distributed parallel objects.
Filters can be executed on :class:`vtkm::cont::PartitionedDataSet` objects in a similar way they are executed on :class:`vtkm::cont::DataSet` objects.
In both cases, the :func:`vtkm::cont::Filter::Execute` method is called on the filter giving data object as an argument.
.. load-example:: FilterPartitionedDataSet
:file: GuideExampleDataSetCreation.cxx
:caption: Applying a filter to multi block data.

@ -0,0 +1,114 @@
==============================
Error Handling
==============================
|VTKm| contains several mechanisms for checking and reporting error conditions.
------------------------------
Runtime Error Exceptions
------------------------------
.. index::
double: errors; control environment
|VTKm| uses exceptions to report errors.
All exceptions thrown by |VTKm| will be a subclass of :class:`vtkm::cont::Error`.
For simple error reporting, it is possible to simply catch a :class:`vtkm::cont::Error` and report the error message string reported by the :func:`vtkm::cont::Error::GetMessage` method.
.. load-example:: CatchingErrors
:file: GuideExampleErrorHandling.cxx
:caption: Simple error reporting.
.. doxygenclass:: vtkm::cont::Error
:members:
There are several subclasses to :class:`vtkm::cont::Error`.
The specific subclass gives an indication of the type of error that occurred when the exception was thrown.
Catching one of these subclasses may help a program better recover from errors.
.. doxygenclass:: vtkm::cont::ErrorBadAllocation
:members:
.. doxygenclass:: vtkm::cont::ErrorBadDevice
:members:
.. doxygenclass:: vtkm::cont::ErrorBadType
:members:
.. doxygenclass:: vtkm::cont::ErrorBadValue
:members:
.. doxygenclass:: vtkm::cont::ErrorExecution
:members:
.. doxygenclass:: vtkm::cont::ErrorFilterExecution
:members:
.. doxygenclass:: vtkm::cont::ErrorInternal
:members:
.. doxygenclass:: vtkm::cont::ErrorUserAbort
:members:
.. doxygenclass:: vtkm::io::ErrorIO
:members:
------------------------------
Asserting Conditions
------------------------------
.. index::
double: errors; assert
In addition to the aforementioned error signaling, the ``vtkm/Assert.h`` header file defines a macro named :c:macro:`VTKM_ASSERT`.
This macro behaves the same as the POSIX :c:macro:`assert` macro.
It takes a single argument that is a condition that is expected to be true.
If it is not true, the program is halted and a message is printed.
Asserts are useful debugging tools to ensure that software is behaving and being used as expected.
.. load-example:: Assert
:file: GuideExampleErrorHandling.cxx
:caption: Using :c:macro:`VTKM_ASSERT`.
.. didyouknow::
Like the POSIX :c:macro:`assert`, if the :c:macro:`NDEBUG` macro is defined, then :c:macro:`VTKM_ASSERT` will become an empty expression.
Typically :c:macro:`NDEBUG` is defined with a compiler flag (like ``-DNDEBUG``) for release builds to better optimize the code.
CMake will automatically add this flag for release builds.
.. commonerrors::
A helpful warning provided by many compilers alerts you of unused variables.
(This warning is commonly enabled on |VTKm| regression test nightly builds.)
If a function argument is used only in a :c:macro:`VTKM_ASSERT`, then it will be required for debug builds and be unused in release builds.
To get around this problem, add a statement to the function of the form ``(void)variableName;``.
This statement will have no effect on the code generated but will suppress the warning for release builds.
------------------------------
Compile Time Checks
------------------------------
.. index::
single: assert; static
single: static assert
Because |VTKm| makes heavy use of C++ templates, it is possible that these templates could be used with inappropriate types in the arguments.
Using an unexpected type in a template can lead to very confusing errors, so it is better to catch such problems as early as possible.
The :c:macro:`VTKM_STATIC_ASSERT` macro, defined in ``vtkm/StaticAssert.h`` makes this possible.
This macro takes a constant expression that can be evaluated at compile time and verifies that the result is true.
In the following example, :c:macro:`VTKM_STATIC_ASSERT` and its sister macro :c:macro:`VTKM_STATIC_ASSERT_MSG`, which allows you to give a descriptive message for the failure, are used to implement checks on a templated function that is designed to work on any scalar type that is represented by 32 or more bits.
.. load-example:: StaticAssert
:file: GuideExampleErrorHandling.cxx
:caption: Using :c:macro:`VTKM_STATIC_ASSERT`.
.. didyouknow::
In addition to the several trait template classes provided by |VTKm| to introspect C++ types, the C++ standard ``type_traits`` header file contains several helpful templates for general queries on types.
:numref:`ex:StaticAssert` demonstrates the use of one such template: ``std::is_same``.
.. commonerrors::
Many templates used to introspect types resolve to the tags ``std::true_type`` and ``std::false_type`` rather than the constant values ``true`` and ``false`` that :c:macro:`VTKM_STATIC_ASSERT` expects.
The ``std::true_type`` and ``std::false_type`` tags can be converted to the Boolean literal by adding ``::value`` to the end of them.
Failing to do so will cause :c:macro:`VTKM_STATIC_ASSERT` to behave incorrectly.
:numref:`ex:StaticAssert` demonstrates getting the Boolean literal from the result of ``std::is_same``.

@ -9,11 +9,36 @@
##============================================================================
set(examples
GuideExampleColorTables.cxx
GuideExampleCoreDataTypes.cxx
GuideExampleInitialization.cxx
GuideExampleIO.cxx
GuideExampleProvidedFilters.cxx
GuideExampleRendering.cxx
GuideExampleRuntimeDeviceTracker.cxx
GuideExampleTimer.cxx
)
set(examples_device
GuideExampleDataSetCreation.cxx # Uses CellSetPartitioned
GuideExampleErrorHandling.cxx # Calls worklet
)
set(extra_libs)
vtkm_find_gl(OPTIONAL GL GLUT)
if(TARGET GLUT::GLUT)
list(APPEND examples
GuideExampleRenderingInteractive.cxx
)
list(APPEND extra_libs OpenGL::GL GLUT::GLUT)
else()
message("Not building OpenGL tutorial examples because GL/GLUT not found.")
endif()
vtkm_unit_tests(
SOURCES ${examples}
DEVICE_SOURCES ${examples_device}
LIBRARIES ${extra_libs}
TEST_ARGS "--no-interaction"
)
# Special example that is an encapsulated program

@ -0,0 +1,111 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/cont/ColorTable.h>
#include <vtkm/rendering/CanvasRayTracer.h>
#include <vtkm/cont/testing/Testing.h>
#include <sys/stat.h>
#include <fstream>
namespace
{
static const vtkm::Id TABLE_IMAGE_WIDTH = 150;
static const vtkm::Id TABLE_IMAGE_HEIGHT = 20;
std::string FilenameFriendly(const std::string& name)
{
std::string filename;
for (auto&& ch : name)
{
if (((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) ||
((ch >= '0') && (ch <= '9')))
{
filename.push_back(ch);
}
else
{
filename.push_back('-');
}
}
return filename;
}
void CreateColorTableImage(const std::string& name)
{
std::cout << "Creating color table " << name << std::endl;
vtkm::cont::ColorTable colorTable(name);
// Create a CanvasRayTracer simply for the color buffer and the ability to
// write out images.
vtkm::rendering::CanvasRayTracer canvas(TABLE_IMAGE_WIDTH, TABLE_IMAGE_HEIGHT);
using ColorBufferType = vtkm::rendering::CanvasRayTracer::ColorBufferType;
ColorBufferType colorBuffer = canvas.GetColorBuffer();
ColorBufferType::WritePortalType colorPortal = colorBuffer.WritePortal();
VTKM_TEST_ASSERT(colorPortal.GetNumberOfValues() ==
TABLE_IMAGE_WIDTH * TABLE_IMAGE_HEIGHT,
"Wrong size of color buffer.");
vtkm::cont::ArrayHandle<vtkm::Vec4ui_8> temp;
colorTable.Sample(TABLE_IMAGE_WIDTH, temp);
constexpr vtkm::Float32 conversionToFloatSpace = (1.0f / 255.0f);
for (vtkm::Id j = 0; j < TABLE_IMAGE_HEIGHT; ++j)
{
auto tempPortal = temp.ReadPortal();
for (vtkm::Id i = 0; i < TABLE_IMAGE_WIDTH; ++i)
{
auto color = tempPortal.Get(i);
vtkm::Vec4f_32 t(color[0] * conversionToFloatSpace,
color[1] * conversionToFloatSpace,
color[2] * conversionToFloatSpace,
color[3] * conversionToFloatSpace);
colorPortal.Set(j * TABLE_IMAGE_WIDTH + i, t);
}
}
canvas.SaveAs("color-tables/" + FilenameFriendly(name) + ".png");
}
void DoColorTables()
{
#ifndef VTKM_MSVC
// Disabled for MSVC because POSIX mkdir is not supported.
// We can use std::filestyem::create_directories later when we support C++17.
mkdir("color-tables", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
std::ofstream rstTable("color-tables/color-table-presets.rst",
std::ios::out | std::ios::trunc);
rstTable << ".. DO NOT EDIT!\n";
rstTable << ".. Created by GuideExampleColorTables test.\n";
rstTable << "\n";
vtkm::cont::ColorTable table;
std::set<std::string> names = table.GetPresets();
for (auto& n : names)
{
CreateColorTableImage(n);
rstTable << ".. |" << FilenameFriendly(n) << "| image:: images/color-tables/"
<< FilenameFriendly(n) << ".png\n";
}
#endif
}
} // anonymous namespace
int GuideExampleColorTables(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(DoColorTables, argc, argv);
}

@ -0,0 +1,652 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/cont/BoundsCompute.h>
#include <vtkm/cont/CellSetPermutation.h>
#include <vtkm/cont/DataSetBuilderExplicit.h>
#include <vtkm/cont/DataSetBuilderRectilinear.h>
#include <vtkm/cont/DataSetBuilderUniform.h>
#include <vtkm/cont/FieldRangeCompute.h>
#include <vtkm/cont/PartitionedDataSet.h>
#include <vtkm/cont/UncertainCellSet.h>
#include <vtkm/filter/field_conversion/CellAverage.h>
#include <vtkm/Math.h>
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
namespace DataSetCreationNamespace
{
namespace can_convert_example
{
////
//// BEGIN-EXAMPLE UnknownCellSetCanConvert
////
VTKM_CONT vtkm::Id3 Get3DPointDimensions(
const vtkm::cont::UnknownCellSet& unknownCellSet)
{
if (unknownCellSet.CanConvert<vtkm::cont::CellSetStructured<3>>())
{
vtkm::cont::CellSetStructured<3> cellSet;
unknownCellSet.AsCellSet(cellSet);
return cellSet.GetPointDimensions();
}
else if (unknownCellSet.CanConvert<vtkm::cont::CellSetStructured<2>>())
{
vtkm::cont::CellSetStructured<2> cellSet;
unknownCellSet.AsCellSet(cellSet);
vtkm::Id2 dims = cellSet.GetPointDimensions();
return vtkm::Id3{ dims[0], dims[1], 1 };
}
else
{
return vtkm::Id3{ unknownCellSet.GetNumberOfPoints(), 1, 1 };
}
}
////
//// END-EXAMPLE UnknownCellSetCanConvert
////
} // namespace can_convert_example
namespace cast_and_call_for_types_example
{
////
//// BEGIN-EXAMPLE UnknownCellSetCastAndCallForTypes
////
struct Get3DPointDimensionsFunctor
{
template<vtkm::IdComponent Dims>
VTKM_CONT void operator()(const vtkm::cont::CellSetStructured<Dims>& cellSet,
vtkm::Id3& outDims) const
{
vtkm::Vec<vtkm::Id, Dims> pointDims = cellSet.GetPointDimensions();
for (vtkm::IdComponent d = 0; d < Dims; ++d)
{
outDims[d] = pointDims[d];
}
}
VTKM_CONT void operator()(const vtkm::cont::CellSet& cellSet, vtkm::Id3& outDims) const
{
outDims[0] = cellSet.GetNumberOfPoints();
}
};
VTKM_CONT vtkm::Id3 Get3DPointDimensions(
const vtkm::cont::UnknownCellSet& unknownCellSet)
{
vtkm::Id3 dims(1);
unknownCellSet.CastAndCallForTypes<VTKM_DEFAULT_CELL_SET_LIST>(
Get3DPointDimensionsFunctor{}, dims);
return dims;
}
////
//// END-EXAMPLE UnknownCellSetCastAndCallForTypes
////
VTKM_CONT vtkm::Id3 Get3DStructuredPointDimensions(
const vtkm::cont::UnknownCellSet& unknownCellSet)
{
vtkm::Id3 dims;
////
//// BEGIN-EXAMPLE UncertainCellSet
////
using StructuredCellSetList = vtkm::List<vtkm::cont::CellSetStructured<1>,
vtkm::cont::CellSetStructured<2>,
vtkm::cont::CellSetStructured<3>>;
vtkm::cont::UncertainCellSet<StructuredCellSetList> uncertainCellSet(unknownCellSet);
uncertainCellSet.CastAndCall(Get3DPointDimensionsFunctor{}, dims);
////
//// END-EXAMPLE UncertainCellSet
////
return dims;
}
} // namespace cast_and_call_for_types_example
struct MyWorklet : vtkm::worklet::WorkletVisitCellsWithPoints
{
using ControlSignature = void(CellSetIn, FieldOutCell);
using ExecutionSignature = _2(IncidentElementCount);
VTKM_EXEC vtkm::IdComponent operator()(vtkm::IdComponent pointCount) const
{
return pointCount;
}
};
void CreateUniformGrid()
{
std::cout << "Creating uniform grid." << std::endl;
////
//// BEGIN-EXAMPLE CreateUniformGrid
////
vtkm::cont::DataSetBuilderUniform dataSetBuilder;
vtkm::cont::DataSet dataSet = dataSetBuilder.Create(vtkm::Id3(101, 101, 26));
////
//// END-EXAMPLE CreateUniformGrid
////
vtkm::Bounds bounds = dataSet.GetCoordinateSystem().GetBounds();
std::cout << bounds << std::endl;
VTKM_TEST_ASSERT(test_equal(bounds, vtkm::Bounds(0, 100, 0, 100, 0, 25)),
"Bad bounds");
vtkm::cont::UnknownCellSet unknownCellSet = dataSet.GetCellSet();
VTKM_TEST_ASSERT(can_convert_example::Get3DPointDimensions(unknownCellSet) ==
vtkm::Id3(101, 101, 26));
VTKM_TEST_ASSERT(cast_and_call_for_types_example::Get3DPointDimensions(
unknownCellSet) == vtkm::Id3(101, 101, 26));
VTKM_TEST_ASSERT(cast_and_call_for_types_example::Get3DStructuredPointDimensions(
unknownCellSet) == vtkm::Id3(101, 101, 26));
vtkm::cont::ArrayHandle<vtkm::IdComponent> outArray;
////
//// BEGIN-EXAMPLE UnknownCellSetResetCellSetList
////
using StructuredCellSetList = vtkm::List<vtkm::cont::CellSetStructured<1>,
vtkm::cont::CellSetStructured<2>,
vtkm::cont::CellSetStructured<3>>;
vtkm::cont::Invoker invoke;
invoke(
MyWorklet{}, unknownCellSet.ResetCellSetList<StructuredCellSetList>(), outArray);
////
//// END-EXAMPLE UnknownCellSetResetCellSetList
////
}
void CreateUniformGridCustomOriginSpacing()
{
std::cout << "Creating uniform grid with custom origin and spacing." << std::endl;
////
//// BEGIN-EXAMPLE CreateUniformGridCustomOriginSpacing
////
vtkm::cont::DataSetBuilderUniform dataSetBuilder;
vtkm::cont::DataSet dataSet = dataSetBuilder.Create(vtkm::Id3(101, 101, 26),
vtkm::Vec3f(-50.0, -50.0, -50.0),
vtkm::Vec3f(1.0, 1.0, 4.0));
////
//// END-EXAMPLE CreateUniformGridCustomOriginSpacing
////
vtkm::Bounds bounds = dataSet.GetCoordinateSystem().GetBounds();
std::cout << bounds << std::endl;
VTKM_TEST_ASSERT(test_equal(bounds, vtkm::Bounds(-50, 50, -50, 50, -50, 50)),
"Bad bounds");
}
void CreateRectilinearGrid()
{
std::cout << "Create rectilinear grid." << std::endl;
////
//// BEGIN-EXAMPLE CreateRectilinearGrid
////
// Make x coordinates range from -4 to 4 with tighter spacing near 0.
std::vector<vtkm::Float32> xCoordinates;
for (vtkm::Float32 x = -2.0f; x <= 2.0f; x += 0.02f)
{
xCoordinates.push_back(vtkm::CopySign(x * x, x));
}
// Make y coordinates range from 0 to 2 with tighter spacing near 2.
std::vector<vtkm::Float32> yCoordinates;
for (vtkm::Float32 y = 0.0f; y <= 4.0f; y += 0.02f)
{
yCoordinates.push_back(vtkm::Sqrt(y));
}
// Make z coordinates rangefrom -1 to 1 with even spacing.
std::vector<vtkm::Float32> zCoordinates;
for (vtkm::Float32 z = -1.0f; z <= 1.0f; z += 0.02f)
{
zCoordinates.push_back(z);
}
vtkm::cont::DataSetBuilderRectilinear dataSetBuilder;
vtkm::cont::DataSet dataSet =
dataSetBuilder.Create(xCoordinates, yCoordinates, zCoordinates);
////
//// END-EXAMPLE CreateRectilinearGrid
////
vtkm::Id numPoints = dataSet.GetCellSet().GetNumberOfPoints();
std::cout << "Num points: " << numPoints << std::endl;
VTKM_TEST_ASSERT(numPoints == 4080501, "Got wrong number of points.");
vtkm::Bounds bounds = dataSet.GetCoordinateSystem().GetBounds();
std::cout << bounds << std::endl;
VTKM_TEST_ASSERT(test_equal(bounds, vtkm::Bounds(-4, 4, 0, 2, -1, 1)), "Bad bounds");
}
void CreateExplicitGrid()
{
std::cout << "Creating explicit grid." << std::endl;
////
//// BEGIN-EXAMPLE CreateExplicitGrid
////
// Array of point coordinates.
std::vector<vtkm::Vec3f_32> pointCoordinates;
pointCoordinates.push_back(vtkm::Vec3f_32(1.1f, 0.0f, 0.0f));
pointCoordinates.push_back(vtkm::Vec3f_32(0.2f, 0.4f, 0.0f));
pointCoordinates.push_back(vtkm::Vec3f_32(0.9f, 0.6f, 0.0f));
pointCoordinates.push_back(vtkm::Vec3f_32(1.4f, 0.5f, 0.0f));
pointCoordinates.push_back(vtkm::Vec3f_32(1.8f, 0.3f, 0.0f));
pointCoordinates.push_back(vtkm::Vec3f_32(0.4f, 1.0f, 0.0f));
pointCoordinates.push_back(vtkm::Vec3f_32(1.0f, 1.2f, 0.0f));
pointCoordinates.push_back(vtkm::Vec3f_32(1.5f, 0.9f, 0.0f));
// Array of shapes.
std::vector<vtkm::UInt8> shapes;
shapes.push_back(vtkm::CELL_SHAPE_TRIANGLE);
shapes.push_back(vtkm::CELL_SHAPE_QUAD);
shapes.push_back(vtkm::CELL_SHAPE_TRIANGLE);
shapes.push_back(vtkm::CELL_SHAPE_POLYGON);
shapes.push_back(vtkm::CELL_SHAPE_TRIANGLE);
// Array of number of indices per cell.
std::vector<vtkm::IdComponent> numIndices;
numIndices.push_back(3);
numIndices.push_back(4);
numIndices.push_back(3);
numIndices.push_back(5);
numIndices.push_back(3);
// Connectivity array.
std::vector<vtkm::Id> connectivity;
connectivity.push_back(0); // Cell 0
connectivity.push_back(2);
connectivity.push_back(1);
connectivity.push_back(0); // Cell 1
connectivity.push_back(4);
connectivity.push_back(3);
connectivity.push_back(2);
connectivity.push_back(1); // Cell 2
connectivity.push_back(2);
connectivity.push_back(5);
connectivity.push_back(2); // Cell 3
connectivity.push_back(3);
connectivity.push_back(7);
connectivity.push_back(6);
connectivity.push_back(5);
connectivity.push_back(3); // Cell 4
connectivity.push_back(4);
connectivity.push_back(7);
// Copy these arrays into a DataSet.
vtkm::cont::DataSetBuilderExplicit dataSetBuilder;
vtkm::cont::DataSet dataSet =
dataSetBuilder.Create(pointCoordinates, shapes, numIndices, connectivity);
////
//// END-EXAMPLE CreateExplicitGrid
////
vtkm::cont::CellSetExplicit<> cellSet;
dataSet.GetCellSet().AsCellSet(cellSet);
VTKM_TEST_ASSERT(test_equal(cellSet.GetNumberOfPoints(), 8),
"Data set has wrong number of points.");
VTKM_TEST_ASSERT(test_equal(cellSet.GetNumberOfCells(), 5),
"Data set has wrong number of cells.");
vtkm::Bounds bounds = dataSet.GetCoordinateSystem().GetBounds();
std::cout << bounds << std::endl;
VTKM_TEST_ASSERT(test_equal(bounds, vtkm::Bounds(0.2, 1.8, 0.0, 1.2, 0.0, 0.0)),
"Bad bounds");
// Do a simple check of the connectivity by getting the number of cells
// incident on each point. This array is unlikely to be correct if the
// topology got screwed up.
auto numCellsPerPoint = cellSet.GetNumIndicesArray(vtkm::TopologyElementTagPoint(),
vtkm::TopologyElementTagCell());
vtkm::cont::printSummary_ArrayHandle(numCellsPerPoint, std::cout);
std::cout << std::endl;
auto numCellsPortal = numCellsPerPoint.ReadPortal();
VTKM_TEST_ASSERT(test_equal(numCellsPortal.Get(0), 2),
"Wrong number of cells on point 0");
VTKM_TEST_ASSERT(test_equal(numCellsPortal.Get(1), 2),
"Wrong number of cells on point 1");
VTKM_TEST_ASSERT(test_equal(numCellsPortal.Get(2), 4),
"Wrong number of cells on point 2");
VTKM_TEST_ASSERT(test_equal(numCellsPortal.Get(3), 3),
"Wrong number of cells on point 3");
VTKM_TEST_ASSERT(test_equal(numCellsPortal.Get(4), 2),
"Wrong number of cells on point 4");
VTKM_TEST_ASSERT(test_equal(numCellsPortal.Get(5), 2),
"Wrong number of cells on point 5");
VTKM_TEST_ASSERT(test_equal(numCellsPortal.Get(6), 1),
"Wrong number of cells on point 6");
VTKM_TEST_ASSERT(test_equal(numCellsPortal.Get(7), 2),
"Wrong number of cells on point 7");
}
void CreateExplicitGridIterative()
{
std::cout << "Creating explicit grid iteratively." << std::endl;
////
//// BEGIN-EXAMPLE CreateExplicitGridIterative
////
vtkm::cont::DataSetBuilderExplicitIterative dataSetBuilder;
dataSetBuilder.AddPoint(1.1, 0.0, 0.0);
dataSetBuilder.AddPoint(0.2, 0.4, 0.0);
dataSetBuilder.AddPoint(0.9, 0.6, 0.0);
dataSetBuilder.AddPoint(1.4, 0.5, 0.0);
dataSetBuilder.AddPoint(1.8, 0.3, 0.0);
dataSetBuilder.AddPoint(0.4, 1.0, 0.0);
dataSetBuilder.AddPoint(1.0, 1.2, 0.0);
dataSetBuilder.AddPoint(1.5, 0.9, 0.0);
dataSetBuilder.AddCell(vtkm::CELL_SHAPE_TRIANGLE);
dataSetBuilder.AddCellPoint(0);
dataSetBuilder.AddCellPoint(2);
dataSetBuilder.AddCellPoint(1);
dataSetBuilder.AddCell(vtkm::CELL_SHAPE_QUAD);
dataSetBuilder.AddCellPoint(0);
dataSetBuilder.AddCellPoint(4);
dataSetBuilder.AddCellPoint(3);
dataSetBuilder.AddCellPoint(2);
dataSetBuilder.AddCell(vtkm::CELL_SHAPE_TRIANGLE);
dataSetBuilder.AddCellPoint(1);
dataSetBuilder.AddCellPoint(2);
dataSetBuilder.AddCellPoint(5);
dataSetBuilder.AddCell(vtkm::CELL_SHAPE_POLYGON);
dataSetBuilder.AddCellPoint(2);
dataSetBuilder.AddCellPoint(3);
dataSetBuilder.AddCellPoint(7);
dataSetBuilder.AddCellPoint(6);
dataSetBuilder.AddCellPoint(5);
dataSetBuilder.AddCell(vtkm::CELL_SHAPE_TRIANGLE);
dataSetBuilder.AddCellPoint(3);
dataSetBuilder.AddCellPoint(4);
dataSetBuilder.AddCellPoint(7);
vtkm::cont::DataSet dataSet = dataSetBuilder.Create();
////
//// END-EXAMPLE CreateExplicitGridIterative
////
vtkm::cont::UnknownCellSet unknownCells = dataSet.GetCellSet();
////
//// BEGIN-EXAMPLE UnknownCellSetAsCellSet
////
vtkm::cont::CellSetExplicit<> cellSet;
unknownCells.AsCellSet(cellSet);
// This is an equivalent way to get the cell set.
auto cellSet2 = unknownCells.AsCellSet<vtkm::cont::CellSetExplicit<>>();
////
//// END-EXAMPLE UnknownCellSetAsCellSet
////
VTKM_STATIC_ASSERT((std::is_same<decltype(cellSet), decltype(cellSet2)>::value));
VTKM_TEST_ASSERT(cellSet.GetConnectivityArray(vtkm::TopologyElementTagCell{},
vtkm::TopologyElementTagPoint{}) ==
cellSet2.GetConnectivityArray(vtkm::TopologyElementTagCell{},
vtkm::TopologyElementTagPoint{}));
VTKM_TEST_ASSERT(test_equal(cellSet.GetNumberOfPoints(), 8),
"Data set has wrong number of points.");
VTKM_TEST_ASSERT(test_equal(cellSet.GetNumberOfCells(), 5),
"Data set has wrong number of cells.");
vtkm::Bounds bounds = dataSet.GetCoordinateSystem().GetBounds();
std::cout << bounds << std::endl;
VTKM_TEST_ASSERT(test_equal(bounds, vtkm::Bounds(0.2, 1.8, 0.0, 1.2, 0.0, 0.0)),
"Bad bounds");
// Do a simple check of the connectivity by getting the number of cells
// incident on each point. This array is unlikely to be correct if the
// topology got screwed up.
auto numCellsPerPoint = cellSet.GetNumIndicesArray(vtkm::TopologyElementTagPoint(),
vtkm::TopologyElementTagCell());
vtkm::cont::printSummary_ArrayHandle(numCellsPerPoint, std::cout);
std::cout << std::endl;
auto numCellsPortal = numCellsPerPoint.ReadPortal();
VTKM_TEST_ASSERT(test_equal(numCellsPortal.Get(0), 2),
"Wrong number of cells on point 0");
VTKM_TEST_ASSERT(test_equal(numCellsPortal.Get(1), 2),
"Wrong number of cells on point 1");
VTKM_TEST_ASSERT(test_equal(numCellsPortal.Get(2), 4),
"Wrong number of cells on point 2");
VTKM_TEST_ASSERT(test_equal(numCellsPortal.Get(3), 3),
"Wrong number of cells on point 3");
VTKM_TEST_ASSERT(test_equal(numCellsPortal.Get(4), 2),
"Wrong number of cells on point 4");
VTKM_TEST_ASSERT(test_equal(numCellsPortal.Get(5), 2),
"Wrong number of cells on point 5");
VTKM_TEST_ASSERT(test_equal(numCellsPortal.Get(6), 1),
"Wrong number of cells on point 6");
VTKM_TEST_ASSERT(test_equal(numCellsPortal.Get(7), 2),
"Wrong number of cells on point 7");
}
void AddFieldData()
{
std::cout << "Add field data." << std::endl;
////
//// BEGIN-EXAMPLE AddFieldData
////
// Make a simple structured data set.
const vtkm::Id3 pointDimensions(20, 20, 10);
const vtkm::Id3 cellDimensions = pointDimensions - vtkm::Id3(1, 1, 1);
vtkm::cont::DataSetBuilderUniform dataSetBuilder;
vtkm::cont::DataSet dataSet = dataSetBuilder.Create(pointDimensions);
// Create a field that identifies points on the boundary.
std::vector<vtkm::UInt8> boundaryPoints;
for (vtkm::Id zIndex = 0; zIndex < pointDimensions[2]; zIndex++)
{
for (vtkm::Id yIndex = 0; yIndex < pointDimensions[1]; yIndex++)
{
for (vtkm::Id xIndex = 0; xIndex < pointDimensions[0]; xIndex++)
{
if ((xIndex == 0) || (xIndex == pointDimensions[0] - 1) || (yIndex == 0) ||
(yIndex == pointDimensions[1] - 1) || (zIndex == 0) ||
(zIndex == pointDimensions[2] - 1))
{
boundaryPoints.push_back(1);
}
else
{
boundaryPoints.push_back(0);
}
}
}
}
dataSet.AddPointField("boundary_points", boundaryPoints);
// Create a field that identifies cells on the boundary.
std::vector<vtkm::UInt8> boundaryCells;
for (vtkm::Id zIndex = 0; zIndex < cellDimensions[2]; zIndex++)
{
for (vtkm::Id yIndex = 0; yIndex < cellDimensions[1]; yIndex++)
{
for (vtkm::Id xIndex = 0; xIndex < cellDimensions[0]; xIndex++)
{
if ((xIndex == 0) || (xIndex == cellDimensions[0] - 1) || (yIndex == 0) ||
(yIndex == cellDimensions[1] - 1) || (zIndex == 0) ||
(zIndex == cellDimensions[2] - 1))
{
boundaryCells.push_back(1);
}
else
{
boundaryCells.push_back(0);
}
}
}
}
dataSet.AddCellField("boundary_cells", boundaryCells);
////
//// END-EXAMPLE AddFieldData
////
}
void CreateCellSetPermutation()
{
std::cout << "Create a cell set permutation" << std::endl;
////
//// BEGIN-EXAMPLE CreateCellSetPermutation
////
// Create a simple data set.
vtkm::cont::DataSetBuilderUniform dataSetBuilder;
vtkm::cont::DataSet originalDataSet = dataSetBuilder.Create(vtkm::Id3(33, 33, 26));
vtkm::cont::CellSetStructured<3> originalCellSet;
originalDataSet.GetCellSet().AsCellSet(originalCellSet);
// Create a permutation array for the cells. Each value in the array refers
// to a cell in the original cell set. This particular array selects every
// 10th cell.
vtkm::cont::ArrayHandleCounting<vtkm::Id> permutationArray(0, 10, 2560);
// Create a permutation of that cell set containing only every 10th cell.
vtkm::cont::CellSetPermutation<vtkm::cont::CellSetStructured<3>,
vtkm::cont::ArrayHandleCounting<vtkm::Id>>
permutedCellSet(permutationArray, originalCellSet);
////
//// END-EXAMPLE CreateCellSetPermutation
////
std::cout << "Num points: " << permutedCellSet.GetNumberOfPoints() << std::endl;
VTKM_TEST_ASSERT(permutedCellSet.GetNumberOfPoints() == 28314,
"Wrong number of points.");
std::cout << "Num cells: " << permutedCellSet.GetNumberOfCells() << std::endl;
VTKM_TEST_ASSERT(permutedCellSet.GetNumberOfCells() == 2560, "Wrong number of cells.");
}
void CreatePartitionedDataSet()
{
std::cout << "Creating partitioned data." << std::endl;
////
//// BEGIN-EXAMPLE CreatePartitionedDataSet
////
// Create two uniform data sets
vtkm::cont::DataSetBuilderUniform dataSetBuilder;
vtkm::cont::DataSet dataSet1 = dataSetBuilder.Create(vtkm::Id3(10, 10, 10));
vtkm::cont::DataSet dataSet2 = dataSetBuilder.Create(vtkm::Id3(30, 30, 30));
// Add the datasets to a multi block
vtkm::cont::PartitionedDataSet partitionedData;
partitionedData.AppendPartitions({ dataSet1, dataSet2 });
////
//// END-EXAMPLE CreatePartitionedDataSet
////
VTKM_TEST_ASSERT(partitionedData.GetNumberOfPartitions() == 2,
"Incorrect number of blocks");
}
void QueryPartitionedDataSet()
{
std::cout << "Query on a partitioned data." << std::endl;
vtkm::cont::testing::MakeTestDataSet makeData;
vtkm::cont::PartitionedDataSet partitionedData;
partitionedData.AppendPartitions(
{ makeData.Make2DExplicitDataSet0(), makeData.Make3DExplicitDataSet5() });
////
//// BEGIN-EXAMPLE QueryPartitionedDataSet
////
// Get the bounds of a multi-block data set
vtkm::Bounds bounds = vtkm::cont::BoundsCompute(partitionedData);
// Get the overall min/max of a field named "cellvar"
vtkm::cont::ArrayHandle<vtkm::Range> cellvarRanges =
vtkm::cont::FieldRangeCompute(partitionedData, "cellvar");
// Assuming the "cellvar" field has scalar values, then cellvarRanges has one entry
vtkm::Range cellvarRange = cellvarRanges.ReadPortal().Get(0);
////
//// END-EXAMPLE QueryPartitionedDataSet
////
std::cout << bounds << std::endl;
VTKM_TEST_ASSERT(test_equal(bounds, vtkm::Bounds(0.0, 3.0, 0.0, 4.0, 0.0, 1.0)),
"Bad bounds");
std::cout << cellvarRange << std::endl;
VTKM_TEST_ASSERT(test_equal(cellvarRange, vtkm::Range(0, 130.5)), "Bad range");
}
void FilterPartitionedDataSet()
{
std::cout << "Filter on a partitioned data." << std::endl;
vtkm::cont::testing::MakeTestDataSet makeData;
vtkm::cont::PartitionedDataSet partitionedData;
partitionedData.AppendPartitions(
{ makeData.Make3DUniformDataSet0(), makeData.Make3DUniformDataSet1() });
////
//// BEGIN-EXAMPLE FilterPartitionedDataSet
////
vtkm::filter::field_conversion::CellAverage cellAverage;
cellAverage.SetActiveField("pointvar", vtkm::cont::Field::Association::Points);
vtkm::cont::PartitionedDataSet results = cellAverage.Execute(partitionedData);
////
//// END-EXAMPLE FilterPartitionedDataSet
////
VTKM_TEST_ASSERT(results.GetNumberOfPartitions() == 2, "Incorrect number of blocks.");
}
void Test()
{
CreateUniformGrid();
CreateUniformGridCustomOriginSpacing();
CreateRectilinearGrid();
CreateExplicitGrid();
CreateExplicitGridIterative();
AddFieldData();
CreateCellSetPermutation();
CreatePartitionedDataSet();
QueryPartitionedDataSet();
FilterPartitionedDataSet();
}
} // namespace DataSetCreationNamespace
int GuideExampleDataSetCreation(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(DataSetCreationNamespace::Test, argc, argv);
}

@ -0,0 +1,176 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/Assert.h>
#include <vtkm/StaticAssert.h>
#include <vtkm/TypeTraits.h>
#include <vtkm/cont/ArrayHandleCounting.h>
#include <vtkm/cont/Error.h>
#include <vtkm/cont/ErrorBadValue.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/cont/testing/Testing.h>
#include <chrono>
#include <thread>
#include <type_traits>
namespace ErrorHandlingNamespace
{
////
//// BEGIN-EXAMPLE CatchingErrors
////
int main(int argc, char** argv)
{
//// PAUSE-EXAMPLE
// Suppress unused argument warnings
(void)argv;
//// RESUME-EXAMPLE
try
{
// Do something cool with VTK-m
// ...
//// PAUSE-EXAMPLE
if (argc == 0)
throw vtkm::cont::ErrorBadValue("Oh, no!");
//// RESUME-EXAMPLE
}
catch (const vtkm::cont::Error& error)
{
std::cout << error.GetMessage() << std::endl;
return 1;
}
return 0;
}
////
//// END-EXAMPLE CatchingErrors
////
////
//// BEGIN-EXAMPLE Assert
////
template<typename T>
VTKM_CONT T GetArrayValue(vtkm::cont::ArrayHandle<T> arrayHandle, vtkm::Id index)
{
VTKM_ASSERT(index >= 0);
VTKM_ASSERT(index < arrayHandle.GetNumberOfValues());
////
//// END-EXAMPLE Assert
////
return arrayHandle.ReadPortal().Get(index);
}
VTKM_CONT
void TryGetArrayValue()
{
GetArrayValue(vtkm::cont::make_ArrayHandle({ 2.0, 5.0 }), 0);
GetArrayValue(vtkm::cont::make_ArrayHandle({ 2.0, 5.0 }), 1);
}
////
//// BEGIN-EXAMPLE StaticAssert
////
template<typename T>
VTKM_EXEC_CONT void MyMathFunction(T& value)
{
VTKM_STATIC_ASSERT((std::is_same<typename vtkm::TypeTraits<T>::DimensionalityTag,
vtkm::TypeTraitsScalarTag>::value));
VTKM_STATIC_ASSERT_MSG(sizeof(T) >= 4,
"MyMathFunction needs types with at least 32 bits.");
////
//// END-EXAMPLE StaticAssert
////
for (vtkm::IdComponent iteration = 0; iteration < 5; iteration++)
{
value = value * value;
}
}
VTKM_EXEC_CONT
void TryMyMathFunction()
{
vtkm::Id value(4);
MyMathFunction(value);
}
////
//// BEGIN-EXAMPLE ExecutionErrors
////
struct SquareRoot : vtkm::worklet::WorkletMapField
{
public:
using ControlSignature = void(FieldIn, FieldOut);
using ExecutionSignature = _2(_1);
template<typename T>
VTKM_EXEC T operator()(T x) const
{
if (x < 0)
{
this->RaiseError("Cannot take the square root of a negative number.");
return vtkm::Nan<T>();
}
return vtkm::Sqrt(x);
}
};
////
//// END-EXAMPLE ExecutionErrors
////
VTKM_CONT
void TrySquareRoot()
{
vtkm::cont::ArrayHandle<vtkm::Float32> output;
vtkm::worklet::DispatcherMapField<SquareRoot> dispatcher;
std::cout << "Trying valid input." << std::endl;
vtkm::cont::ArrayHandleCounting<vtkm::Float32> validInput(0.0f, 1.0f, 10);
dispatcher.Invoke(validInput, output);
std::cout << "Trying invalid input." << std::endl;
vtkm::cont::ArrayHandleCounting<vtkm::Float32> invalidInput(-2.0, 1.0f, 10);
bool errorCaught = false;
try
{
dispatcher.Invoke(invalidInput, output);
// Some device adapters are launched asynchronously, and you won't get the error
// until a follow-up call.
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
dispatcher.Invoke(invalidInput, output);
}
catch (const vtkm::cont::ErrorExecution& error)
{
std::cout << "Caught this error:" << std::endl;
std::cout << error.GetMessage() << std::endl;
errorCaught = true;
}
VTKM_TEST_ASSERT(errorCaught, "Did not get expected error.");
}
void Test()
{
VTKM_TEST_ASSERT(ErrorHandlingNamespace::main(0, NULL) != 0, "No error?");
TryGetArrayValue();
TryMyMathFunction();
TrySquareRoot();
}
} // namespace ErrorHandlingNamespace
int GuideExampleErrorHandling(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(ErrorHandlingNamespace::Test, argc, argv);
}

@ -0,0 +1,161 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
////
//// BEGIN-EXAMPLE VTKDataSetWriter
////
#include <vtkm/io/VTKDataSetWriter.h>
void SaveDataAsVTKFile(vtkm::cont::DataSet data)
{
vtkm::io::VTKDataSetWriter writer("data.vtk");
writer.WriteDataSet(data);
}
////
//// END-EXAMPLE VTKDataSetWriter
////
////
//// BEGIN-EXAMPLE VTKDataSetReader
////
#include <vtkm/io/VTKDataSetReader.h>
vtkm::cont::DataSet OpenDataFromVTKFile()
{
vtkm::io::VTKDataSetReader reader("data.vtk");
return reader.ReadDataSet();
}
////
//// END-EXAMPLE VTKDataSetReader
////
////
//// BEGIN-EXAMPLE ImageReaderPNG
////
#include <vtkm/io/ImageReaderPNG.h>
vtkm::cont::DataSet OpenDataFromPNG()
{
vtkm::io::ImageReaderPNG imageReader("data.png");
imageReader.SetPointFieldName("pixel_colors");
return imageReader.ReadDataSet();
}
////
//// END-EXAMPLE ImageReaderPNG
////
////
//// BEGIN-EXAMPLE ImageReaderPNM
////
#include <vtkm/io/ImageReaderPNM.h>
vtkm::cont::DataSet OpenDataFromPNM()
{
vtkm::io::ImageReaderPNM imageReader("data.ppm");
imageReader.SetPointFieldName("pixels");
return imageReader.ReadDataSet();
}
////
//// END-EXAMPLE ImageReaderPNM
////
////
//// BEGIN-EXAMPLE ImageWriterPNG
////
#include <vtkm/io/ImageWriterPNG.h>
void WriteToPNG(const vtkm::cont::DataSet& dataSet)
{
vtkm::io::ImageWriterPNG imageWriter("data.png");
imageWriter.SetPixelDepth(vtkm::io::ImageWriterPNG::PixelDepth::PIXEL_16);
imageWriter.WriteDataSet(dataSet);
}
////
//// END-EXAMPLE ImageWriterPNG
////
////
//// BEGIN-EXAMPLE ImageWriterPNM
////
#include <vtkm/io/ImageWriterPNM.h>
void WriteToPNM(const vtkm::cont::DataSet& dataSet)
{
vtkm::io::ImageWriterPNM imageWriter("data.ppm");
imageWriter.SetPixelDepth(vtkm::io::ImageWriterPNM::PixelDepth::PIXEL_16);
imageWriter.WriteDataSet(dataSet);
}
////
//// END-EXAMPLE ImageWriterPNM
////
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/rendering/Canvas.h>
#include <vtkm/rendering/Color.h>
namespace
{
void TestIO()
{
std::cout << "Writing data" << std::endl;
vtkm::cont::testing::MakeTestDataSet makeDataSet;
vtkm::cont::DataSet createdData = makeDataSet.Make3DExplicitDataSetCowNose();
SaveDataAsVTKFile(createdData);
std::cout << "Reading data" << std::endl;
vtkm::cont::DataSet readData = OpenDataFromVTKFile();
const vtkm::cont::CellSet* createdCellSet = createdData.GetCellSet().GetCellSetBase();
const vtkm::cont::CellSet* readCellSet = readData.GetCellSet().GetCellSetBase();
VTKM_TEST_ASSERT(createdCellSet->GetNumberOfCells() == readCellSet->GetNumberOfCells(),
"Createded and read data do not match.");
VTKM_TEST_ASSERT(createdCellSet->GetNumberOfPoints() ==
readCellSet->GetNumberOfPoints(),
"Createded and read data do not match.");
std::cout << "Reading and writing image data" << std::endl;
vtkm::Bounds colorBarBounds(-0.8, -0.6, -0.8, 0.8, 0, 0);
vtkm::rendering::Canvas canvas(64, 64);
canvas.SetBackgroundColor(vtkm::rendering::Color::blue);
canvas.Clear();
canvas.AddColorBar(colorBarBounds, vtkm::cont::ColorTable("inferno"), false);
canvas.BlendBackground();
vtkm::cont::DataSet imageSource = canvas.GetDataSet("color", nullptr);
WriteToPNG(imageSource);
WriteToPNM(imageSource);
using CheckType = typename vtkm::cont::ArrayHandle<vtkm::Vec4f_32>;
readData = OpenDataFromPNG();
VTKM_TEST_ASSERT(readData.HasPointField("pixel_colors"),
"Point Field Not Found: pixel-data");
vtkm::cont::Field colorField = readData.GetPointField("pixel_colors");
VTKM_TEST_ASSERT(colorField.GetNumberOfValues() == 64 * 64, "wrong image dimensions");
VTKM_TEST_ASSERT(colorField.GetData().IsType<CheckType>(), "wrong ArrayHandle type");
readData = OpenDataFromPNM();
VTKM_TEST_ASSERT(readData.HasPointField("pixels"),
"Point Field Not Found: pixel-data");
colorField = readData.GetPointField("pixels");
VTKM_TEST_ASSERT(colorField.GetNumberOfValues() == 64 * 64, "wrong image dimensions");
VTKM_TEST_ASSERT(colorField.GetData().IsType<CheckType>(), "wrong ArrayHandle type");
}
} // namespace
int GuideExampleIO(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(TestIO, argc, argv);
}

@ -0,0 +1,211 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
////
//// BEGIN-EXAMPLE BasicInitialize
////
#include <vtkm/cont/Initialize.h>
//// PAUSE-EXAMPLE
#include <vtkm/Version.h>
#include <vtkm/cont/Logging.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
namespace InitExample
{
//// RESUME-EXAMPLE
int main(int argc, char** argv)
{
vtkm::cont::InitializeOptions options =
vtkm::cont::InitializeOptions::ErrorOnBadOption |
vtkm::cont::InitializeOptions::DefaultAnyDevice;
vtkm::cont::InitializeResult config = vtkm::cont::Initialize(argc, argv, options);
if (argc != 2)
{
std::cerr << "USAGE: " << argv[0] << " [options] filename" << std::endl;
std::cerr << "Available options are:" << std::endl;
std::cerr << config.Usage << std::endl;
return 1;
}
std::string filename = argv[1];
// Do something cool with VTK-m
// ...
return 0;
}
////
//// END-EXAMPLE BasicInitialize
////
} // namespace InitExample
namespace LoggingExample
{
////
//// BEGIN-EXAMPLE InitializeLogging
////
static const vtkm::cont::LogLevel CustomLogLevel = vtkm::cont::LogLevel::UserFirst;
int main(int argc, char** argv)
{
vtkm::cont::SetLogLevelName(CustomLogLevel, "custom");
// For this example we will set the log level manually.
// The user can override this with the --vtkm-log-level command line flag.
vtkm::cont::SetStderrLogLevel(CustomLogLevel);
vtkm::cont::Initialize(argc, argv);
// Do interesting stuff...
////
//// END-EXAMPLE InitializeLogging
////
return 0;
}
////
//// BEGIN-EXAMPLE ScopedFunctionLogging
////
void TestFunc()
{
VTKM_LOG_SCOPE_FUNCTION(vtkm::cont::LogLevel::Info);
VTKM_LOG_S(vtkm::cont::LogLevel::Info, "Showcasing function logging");
}
////
//// END-EXAMPLE ScopedFunctionLogging
////
////
//// BEGIN-EXAMPLE HelperLogFunctions
////
template<typename T>
void DoSomething(T&& x)
{
VTKM_LOG_S(CustomLogLevel,
"Doing something with type " << vtkm::cont::TypeToString<T>());
vtkm::Id arraySize = 100000 * sizeof(T);
VTKM_LOG_S(CustomLogLevel,
"Size of array is " << vtkm::cont::GetHumanReadableSize(arraySize));
VTKM_LOG_S(CustomLogLevel,
"More precisely it is " << vtkm::cont::GetSizeString(arraySize, 4));
VTKM_LOG_S(CustomLogLevel, "Stack location: " << vtkm::cont::GetStackTrace());
////
//// END-EXAMPLE HelperLogFunctions
////
(void)x;
}
void ExampleLogging()
{
////
//// BEGIN-EXAMPLE BasicLogging
////
VTKM_LOG_F(vtkm::cont::LogLevel::Info,
"Base VTK-m version: %d.%d",
VTKM_VERSION_MAJOR,
VTKM_VERSION_MINOR);
VTKM_LOG_S(vtkm::cont::LogLevel::Info, "Full VTK-m version: " << VTKM_VERSION_FULL);
////
//// END-EXAMPLE BasicLogging
////
////
//// BEGIN-EXAMPLE ConditionalLogging
////
for (size_t i = 0; i < 5; i++)
{
VTKM_LOG_IF_S(vtkm::cont::LogLevel::Info, i % 2 == 0, "Found an even number: " << i);
}
////
//// END-EXAMPLE ConditionalLogging
////
constexpr vtkm::IdComponent numTrials = 3;
////
//// BEGIN-EXAMPLE ScopedLogging
////
for (vtkm::IdComponent trial = 0; trial < numTrials; ++trial)
{
VTKM_LOG_SCOPE(CustomLogLevel, "Trial %d", trial);
VTKM_LOG_F(CustomLogLevel, "Do thing 1");
VTKM_LOG_F(CustomLogLevel, "Do thing 2");
//...
}
////
//// END-EXAMPLE ScopedLogging
////
TestFunc();
DoSomething(vtkm::Vec<vtkm::Id3, 3>{});
#if 0
Error context was removed in VTK-m 2.0 (and was disabled long before then)
//
// BEGIN-EXAMPLE LoggingErrorContext
//
// This message is only logged if a crash occurs
VTKM_LOG_ERROR_CONTEXT("Some variable value", 42);
//
// END-EXAMPLE LoggingErrorContext
//
std::cerr << vtkm::cont::GetLogErrorContext() << "\n";
#endif
}
} // namespace LoggingExample
void Test(int argc, char** argv)
{
LoggingExample::main(argc, argv);
LoggingExample::ExampleLogging();
std::string arg0 = "command-name";
std::string arg1 = "--vtkm-device=any";
std::string arg2 = "filename";
std::vector<char*> fakeArgv;
fakeArgv.push_back(const_cast<char*>(arg0.c_str()));
fakeArgv.push_back(const_cast<char*>(arg1.c_str()));
fakeArgv.push_back(const_cast<char*>(arg2.c_str()));
InitExample::main(3, &fakeArgv.front());
}
} // anonymous namespace
int GuideExampleInitialization(int argc, char* argv[])
{
// Do not use standard testing run because that also calls Initialize
// and will foul up the other calls.
try
{
Test(argc, argv);
}
catch (...)
{
std::cerr << "Uncaught exception" << std::endl;
return 1;
}
return 0;
}

@ -0,0 +1,556 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/filter/contour/ClipWithField.h>
#include <vtkm/filter/contour/ClipWithImplicitFunction.h>
#include <vtkm/filter/contour/Contour.h>
#include <vtkm/filter/field_transform/PointElevation.h>
#include <vtkm/filter/flow/Pathline.h>
#include <vtkm/filter/flow/StreamSurface.h>
#include <vtkm/filter/flow/Streamline.h>
#include <vtkm/filter/geometry_refinement/Tube.h>
#include <vtkm/filter/geometry_refinement/VertexClustering.h>
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/DataSetBuilderExplicit.h>
#include <vtkm/cont/DataSetBuilderUniform.h>
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
////
//// BEGIN-EXAMPLE PointElevation
////
VTKM_CONT
vtkm::cont::DataSet ComputeAirPressure(vtkm::cont::DataSet dataSet)
{
//// LABEL Construct
vtkm::filter::field_transform::PointElevation elevationFilter;
// Use the elevation filter to estimate atmospheric pressure based on the
// height of the point coordinates. Atmospheric pressure is 101325 Pa at
// sea level and drops about 12 Pa per meter.
//// LABEL SetStateStart
elevationFilter.SetLowPoint(0.0, 0.0, 0.0);
elevationFilter.SetHighPoint(0.0, 0.0, 2000.0);
elevationFilter.SetRange(101325.0, 77325.0);
//// LABEL SetInputField
elevationFilter.SetUseCoordinateSystemAsField(true);
//// LABEL SetStateEnd
//// LABEL SetOutputField
elevationFilter.SetOutputFieldName("pressure");
//// LABEL Execute
vtkm::cont::DataSet result = elevationFilter.Execute(dataSet);
return result;
}
////
//// END-EXAMPLE PointElevation
////
void DoPointElevation()
{
std::cout << "** Run elevation filter" << std::endl;
vtkm::cont::testing::MakeTestDataSet makeData;
vtkm::cont::DataSet inData = makeData.Make3DRegularDataSet0();
vtkm::cont::DataSet pressureData = ComputeAirPressure(inData);
pressureData.GetField("pressure").PrintSummary(std::cout);
std::cout << std::endl;
}
void DoVertexClustering()
{
std::cout << "** Run vertex clustering filter" << std::endl;
vtkm::cont::testing::MakeTestDataSet makeData;
vtkm::cont::DataSet originalSurface = makeData.Make3DExplicitDataSetCowNose();
////
//// BEGIN-EXAMPLE VertexClustering
////
vtkm::filter::geometry_refinement::VertexClustering vertexClustering;
vertexClustering.SetNumberOfDivisions(vtkm::Id3(128, 128, 128));
vtkm::cont::DataSet simplifiedSurface = vertexClustering.Execute(originalSurface);
////
//// END-EXAMPLE VertexClustering
////
simplifiedSurface.PrintSummary(std::cout);
std::cout << std::endl;
}
void DoClipWithImplicitFunction()
{
std::cout << "** Run clip with implicit function filter" << std::endl;
vtkm::cont::testing::MakeTestDataSet makeData;
vtkm::cont::DataSet inData = makeData.Make3DUniformDataSet0();
////
//// BEGIN-EXAMPLE ClipWithImplicitFunction
////
////
//// BEGIN-EXAMPLE ImplicitFunctionGeneral
////
// Parameters needed for implicit function
vtkm::Sphere implicitFunction(vtkm::make_Vec(1, 0, 1), 0.5);
// Create an instance of a clip filter with this implicit function.
vtkm::filter::contour::ClipWithImplicitFunction clip;
clip.SetImplicitFunction(implicitFunction);
////
//// END-EXAMPLE ImplicitFunctionGeneral
////
// By default, ClipWithImplicitFunction will remove everything inside the sphere.
// Set the invert clip flag to keep the inside of the sphere and remove everything
// else.
clip.SetInvertClip(true);
// Execute the clip filter
vtkm::cont::DataSet outData = clip.Execute(inData);
////
//// END-EXAMPLE ClipWithImplicitFunction
////
outData.PrintSummary(std::cout);
std::cout << std::endl;
}
void DoContour()
{
std::cout << "** Run Contour filter" << std::endl;
vtkm::cont::testing::MakeTestDataSet makeData;
vtkm::cont::DataSet inData = makeData.Make3DRectilinearDataSet0();
////
//// BEGIN-EXAMPLE Contour
////
vtkm::filter::contour::Contour contour;
contour.SetActiveField("pointvar");
contour.SetIsoValue(10.0);
vtkm::cont::DataSet isosurface = contour.Execute(inData);
////
//// END-EXAMPLE Contour
////
isosurface.PrintSummary(std::cout);
std::cout << std::endl;
vtkm::filter::contour::Contour filter = contour;
////
//// BEGIN-EXAMPLE SetActiveFieldWithAssociation
////
filter.SetActiveField("pointvar", vtkm::cont::Field::Association::Points);
////
//// END-EXAMPLE SetActiveFieldWithAssociation
////
vtkm::cont::DataSet other = filter.Execute(inData);
VTKM_TEST_ASSERT(isosurface.GetNumberOfCells() == other.GetNumberOfCells());
VTKM_TEST_ASSERT(isosurface.GetNumberOfPoints() == other.GetNumberOfPoints());
}
void DoClipWithField()
{
std::cout << "** Run clip with field filter" << std::endl;
vtkm::cont::testing::MakeTestDataSet makeData;
vtkm::cont::DataSet inData = makeData.Make3DUniformDataSet0();
////
//// BEGIN-EXAMPLE ClipWithField
////
// Create an instance of a clip filter that discards all regions with scalar
// value less than 25.
vtkm::filter::contour::ClipWithField clip;
clip.SetClipValue(25.0);
clip.SetActiveField("pointvar");
// Execute the clip filter
vtkm::cont::DataSet outData = clip.Execute(inData);
////
//// END-EXAMPLE ClipWithField
////
outData.PrintSummary(std::cout);
std::cout << std::endl;
}
void DoStreamlines()
{
std::cout << "** Run streamlines filter" << std::endl;
vtkm::cont::DataSetBuilderUniform dataSetBuilder;
vtkm::cont::DataSet inData = dataSetBuilder.Create(vtkm::Id3(5, 5, 5));
vtkm::Id numPoints = inData.GetCellSet().GetNumberOfPoints();
vtkm::cont::ArrayHandle<vtkm::Vec3f> vectorField;
vtkm::cont::ArrayCopy(
vtkm::cont::make_ArrayHandleConstant(vtkm::Vec3f(1, 0, 0), numPoints), vectorField);
inData.AddPointField("vectorvar", vectorField);
////
//// BEGIN-EXAMPLE Streamlines
////
vtkm::filter::flow::Streamline streamlines;
// Specify the seeds.
vtkm::cont::ArrayHandle<vtkm::Particle> seedArray;
seedArray.Allocate(2);
seedArray.WritePortal().Set(0, vtkm::Particle({ 0, 0, 0 }, 0));
seedArray.WritePortal().Set(1, vtkm::Particle({ 1, 1, 1 }, 1));
streamlines.SetActiveField("vectorvar");
streamlines.SetStepSize(0.1f);
streamlines.SetNumberOfSteps(100);
streamlines.SetSeeds(seedArray);
vtkm::cont::DataSet output = streamlines.Execute(inData);
////
//// END-EXAMPLE Streamlines
////
output.PrintSummary(std::cout);
std::cout << std::endl;
}
void DoStreamsurface()
{
std::cout << "** Run streamsurface filter" << std::endl;
vtkm::cont::DataSetBuilderUniform dataSetBuilder;
vtkm::cont::DataSet inData = dataSetBuilder.Create(vtkm::Id3(5, 5, 5));
vtkm::Id numPoints = inData.GetCellSet().GetNumberOfPoints();
vtkm::cont::ArrayHandle<vtkm::Vec3f> vectorField;
vtkm::cont::ArrayCopy(
vtkm::cont::make_ArrayHandleConstant(vtkm::Vec3f(1, 0, 0), numPoints), vectorField);
inData.AddPointField("vectorvar", vectorField);
////
//// BEGIN-EXAMPLE StreamSurface
////
vtkm::filter::flow::StreamSurface streamSurface;
// Specify the seeds.
vtkm::cont::ArrayHandle<vtkm::Particle> seedArray;
seedArray.Allocate(2);
seedArray.WritePortal().Set(0, vtkm::Particle({ 0, 0, 0 }, 0));
seedArray.WritePortal().Set(1, vtkm::Particle({ 1, 1, 1 }, 1));
streamSurface.SetActiveField("vectorvar");
streamSurface.SetStepSize(0.1f);
streamSurface.SetNumberOfSteps(100);
streamSurface.SetSeeds(seedArray);
vtkm::cont::DataSet output = streamSurface.Execute(inData);
////
//// END-EXAMPLE StreamSurface
////
output.PrintSummary(std::cout);
std::cout << std::endl;
}
void DoTube()
{
std::cout << "** Run tube filter" << std::endl;
vtkm::cont::DataSetBuilderExplicitIterative dsb;
std::vector<vtkm::Id> ids;
vtkm::Id pid;
pid = dsb.AddPoint(vtkm::Vec3f(1, 0, 0));
ids.push_back(pid);
pid = dsb.AddPoint(vtkm::Vec3f(2, 1, 0));
ids.push_back(pid);
pid = dsb.AddPoint(vtkm::Vec3f(3, 0, 0));
ids.push_back(pid);
dsb.AddCell(vtkm::CELL_SHAPE_POLY_LINE, ids);
vtkm::cont::DataSet inData = dsb.Create();
////
//// BEGIN-EXAMPLE Tube
////
vtkm::filter::geometry_refinement::Tube tubeFilter;
tubeFilter.SetRadius(0.5f);
tubeFilter.SetNumberOfSides(7);
tubeFilter.SetCapping(true);
vtkm::cont::DataSet output = tubeFilter.Execute(inData);
////
//// END-EXAMPLE Tube
////
output.PrintSummary(std::cout);
std::cout << std::endl;
}
void DoPathlines()
{
std::cout << "** Run pathlines filter" << std::endl;
vtkm::cont::DataSetBuilderUniform dataSetBuilder;
vtkm::cont::DataSet inData1 = dataSetBuilder.Create(vtkm::Id3(5, 5, 5));
vtkm::cont::DataSet inData2 = dataSetBuilder.Create(vtkm::Id3(5, 5, 5));
vtkm::Id numPoints = inData1.GetCellSet().GetNumberOfPoints();
vtkm::cont::ArrayHandle<vtkm::Vec3f> vectorField1;
vtkm::cont::ArrayCopy(
vtkm::cont::make_ArrayHandleConstant(vtkm::Vec3f(1, 0, 0), numPoints), vectorField1);
inData1.AddPointField("vectorvar", vectorField1);
vtkm::cont::ArrayHandle<vtkm::Vec3f> vectorField2;
vtkm::cont::ArrayCopy(
vtkm::cont::make_ArrayHandleConstant(vtkm::Vec3f(0, 1, 0), numPoints), vectorField2);
inData2.AddPointField("vectorvar", vectorField2);
////
//// BEGIN-EXAMPLE Pathlines
////
vtkm::filter::flow::Pathline pathlines;
// Specify the seeds.
vtkm::cont::ArrayHandle<vtkm::Particle> seedArray;
seedArray.Allocate(2);
seedArray.WritePortal().Set(0, vtkm::Particle({ 0, 0, 0 }, 0));
seedArray.WritePortal().Set(1, vtkm::Particle({ 1, 1, 1 }, 1));
pathlines.SetActiveField("vectorvar");
pathlines.SetStepSize(0.1f);
pathlines.SetNumberOfSteps(100);
pathlines.SetSeeds(seedArray);
pathlines.SetPreviousTime(0.0f);
pathlines.SetNextTime(1.0f);
pathlines.SetNextDataSet(inData2);
vtkm::cont::DataSet pathlineCurves = pathlines.Execute(inData1);
////
//// END-EXAMPLE Pathlines
////
pathlineCurves.PrintSummary(std::cout);
std::cout << std::endl;
}
void DoCheckFieldPassing()
{
std::cout << "** Check field passing" << std::endl;
vtkm::cont::testing::MakeTestDataSet makeData;
vtkm::cont::DataSet inData = makeData.Make3DRectilinearDataSet0();
vtkm::cont::ArrayHandle<vtkm::Float32> scalars;
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleConstant<vtkm::Float32>(
1, inData.GetCellSet().GetNumberOfPoints()),
scalars);
inData.AddPointField("scalars", scalars);
vtkm::filter::field_transform::PointElevation filter;
filter.SetLowPoint(0.0, 0.0, 0.0);
filter.SetHighPoint(0.0, 0.0, 1.0);
filter.SetRange(0.0, 1.0);
////
//// BEGIN-EXAMPLE SetCoordinateSystem
////
filter.SetUseCoordinateSystemAsField(true);
filter.SetActiveCoordinateSystem(1);
////
//// END-EXAMPLE SetCoordinateSystem
////
filter.SetActiveCoordinateSystem(0);
filter.SetOutputFieldName("elevation");
{
vtkm::cont::DataSet outData = filter.Execute(inData);
for (vtkm::IdComponent fieldId = 0; fieldId < inData.GetNumberOfFields(); ++fieldId)
{
vtkm::cont::Field inField = inData.GetField(fieldId);
VTKM_TEST_ASSERT(outData.HasField(inField.GetName(), inField.GetAssociation()),
"Did not automatically pass all fields.");
}
}
{
////
//// BEGIN-EXAMPLE PassNoFields
////
filter.SetFieldsToPass(vtkm::filter::FieldSelection::Mode::None);
////
//// END-EXAMPLE PassNoFields
////
////
//// BEGIN-EXAMPLE PassNoCoordinates
////
filter.SetPassCoordinateSystems(false);
////
//// END-EXAMPLE PassNoCoordinates
////
vtkm::cont::DataSet outData = filter.Execute(inData);
VTKM_TEST_ASSERT(outData.GetNumberOfFields() == 1,
"Could not turn off passing of fields");
}
{
////
//// BEGIN-EXAMPLE PassOneField
////
filter.SetFieldsToPass("pointvar");
////
//// END-EXAMPLE PassOneField
////
filter.SetPassCoordinateSystems(false);
vtkm::cont::DataSet outData = filter.Execute(inData);
outData.PrintSummary(std::cout);
VTKM_TEST_ASSERT(outData.GetNumberOfFields() == 2,
"Could not set field passing correctly.");
VTKM_TEST_ASSERT(outData.HasPointField("pointvar"));
}
{
////
//// BEGIN-EXAMPLE PassListOfFields
////
filter.SetFieldsToPass({ "pointvar", "cellvar" });
////
//// END-EXAMPLE PassListOfFields
////
filter.SetPassCoordinateSystems(false);
vtkm::cont::DataSet outData = filter.Execute(inData);
outData.PrintSummary(std::cout);
VTKM_TEST_ASSERT(outData.GetNumberOfFields() == 3,
"Could not set field passing correctly.");
VTKM_TEST_ASSERT(outData.HasPointField("pointvar"));
VTKM_TEST_ASSERT(outData.HasCellField("cellvar"));
}
{
////
//// BEGIN-EXAMPLE PassExcludeFields
////
filter.SetFieldsToPass({ "pointvar", "cellvar" },
vtkm::filter::FieldSelection::Mode::Exclude);
////
//// END-EXAMPLE PassExcludeFields
////
vtkm::cont::DataSet outData = filter.Execute(inData);
outData.PrintSummary(std::cout);
VTKM_TEST_ASSERT(outData.GetNumberOfFields() == (inData.GetNumberOfFields() - 1),
"Could not set field passing correctly.");
VTKM_TEST_ASSERT(outData.HasField("scalars"));
}
{
////
//// BEGIN-EXAMPLE FieldSelection
////
vtkm::filter::FieldSelection fieldSelection;
fieldSelection.AddField("scalars");
fieldSelection.AddField("cellvar", vtkm::cont::Field::Association::Cells);
filter.SetFieldsToPass(fieldSelection);
////
//// END-EXAMPLE FieldSelection
////
filter.SetPassCoordinateSystems(false);
vtkm::cont::DataSet outData = filter.Execute(inData);
outData.PrintSummary(std::cout);
VTKM_TEST_ASSERT(outData.GetNumberOfFields() == 3,
"Could not set field passing correctly.");
VTKM_TEST_ASSERT(outData.HasField("scalars"));
VTKM_TEST_ASSERT(outData.HasCellField("cellvar"));
}
{
////
//// BEGIN-EXAMPLE PassFieldAndAssociation
////
filter.SetFieldsToPass("pointvar", vtkm::cont::Field::Association::Points);
////
//// END-EXAMPLE PassFieldAndAssociation
////
filter.SetPassCoordinateSystems(false);
vtkm::cont::DataSet outData = filter.Execute(inData);
outData.PrintSummary(std::cout);
VTKM_TEST_ASSERT(outData.GetNumberOfFields() == 2,
"Could not set field passing correctly.");
VTKM_TEST_ASSERT(outData.HasPointField("pointvar"));
}
{
////
//// BEGIN-EXAMPLE PassListOfFieldsAndAssociations
////
filter.SetFieldsToPass(
{ vtkm::make_Pair("pointvar", vtkm::cont::Field::Association::Points),
vtkm::make_Pair("cellvar", vtkm::cont::Field::Association::Cells),
vtkm::make_Pair("scalars", vtkm::cont::Field::Association::Any) });
////
//// END-EXAMPLE PassListOfFieldsAndAssociations
////
filter.SetPassCoordinateSystems(false);
vtkm::cont::DataSet outData = filter.Execute(inData);
outData.PrintSummary(std::cout);
VTKM_TEST_ASSERT(outData.GetNumberOfFields() == 4,
"Could not set field passing correctly.");
VTKM_TEST_ASSERT(outData.HasPointField("pointvar"));
VTKM_TEST_ASSERT(outData.HasCellField("cellvar"));
VTKM_TEST_ASSERT(outData.HasField("scalars"));
}
}
void Test()
{
DoPointElevation();
DoVertexClustering();
DoClipWithImplicitFunction();
DoContour();
DoClipWithField();
DoStreamlines();
DoStreamsurface();
DoTube();
DoPathlines();
DoCheckFieldPassing();
}
} // anonymous namespace
int GuideExampleProvidedFilters(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(Test, argc, argv);
}

@ -0,0 +1,214 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/io/VTKDataSetReader.h>
#include <vtkm/rendering/Actor.h>
#include <vtkm/rendering/Camera.h>
#include <vtkm/rendering/CanvasRayTracer.h>
#include <vtkm/rendering/GlyphType.h>
#include <vtkm/rendering/MapperGlyphScalar.h>
#include <vtkm/rendering/MapperRayTracer.h>
#include <vtkm/rendering/MapperWireframer.h>
#include <vtkm/rendering/View3D.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
void DoBasicRender()
{
// Load some data to render
vtkm::cont::DataSet surfaceData;
try
{
vtkm::io::VTKDataSetReader reader(
vtkm::cont::testing::Testing::GetTestDataBasePath() + "unstructured/cow.vtk");
surfaceData = reader.ReadDataSet();
}
catch (vtkm::io::ErrorIO& error)
{
std::cout << "Could not read file:" << std::endl << error.GetMessage() << std::endl;
exit(1);
}
catch (...)
{
throw;
}
// Initialize VTK-m rendering classes
////
//// BEGIN-EXAMPLE ConstructView
////
////
//// BEGIN-EXAMPLE ActorScene
////
vtkm::rendering::Actor actor(surfaceData.GetCellSet(),
surfaceData.GetCoordinateSystem(),
surfaceData.GetField("RandomPointScalars"));
vtkm::rendering::Scene scene;
scene.AddActor(actor);
////
//// END-EXAMPLE ActorScene
////
vtkm::rendering::MapperRayTracer mapper;
////
//// BEGIN-EXAMPLE Canvas
////
vtkm::rendering::CanvasRayTracer canvas(1920, 1080);
////
//// END-EXAMPLE Canvas
////
vtkm::rendering::View3D view(scene, mapper, canvas);
////
//// END-EXAMPLE ConstructView
////
////
//// BEGIN-EXAMPLE ViewColors
////
view.SetBackgroundColor(vtkm::rendering::Color(1.0f, 1.0f, 1.0f));
view.SetForegroundColor(vtkm::rendering::Color(0.0f, 0.0f, 0.0f));
////
//// END-EXAMPLE ViewColors
////
////
//// BEGIN-EXAMPLE PaintView
////
view.Paint();
////
//// END-EXAMPLE PaintView
////
////
//// BEGIN-EXAMPLE SaveView
////
view.SaveAs("BasicRendering.png");
////
//// END-EXAMPLE SaveView
////
}
void DoPointRender()
{
// Load some data to render
vtkm::cont::DataSet surfaceData;
try
{
vtkm::io::VTKDataSetReader reader(
vtkm::cont::testing::Testing::GetTestDataBasePath() + "unstructured/cow.vtk");
surfaceData = reader.ReadDataSet();
}
catch (vtkm::io::ErrorIO& error)
{
std::cout << "Could not read file:" << std::endl << error.GetMessage() << std::endl;
exit(1);
}
catch (...)
{
throw;
}
// Initialize VTK-m rendering classes
vtkm::rendering::Actor actor(surfaceData.GetCellSet(),
surfaceData.GetCoordinateSystem(),
surfaceData.GetField("RandomPointScalars"));
vtkm::rendering::Scene scene;
scene.AddActor(actor);
vtkm::rendering::CanvasRayTracer canvas(1920, 1080);
////
//// BEGIN-EXAMPLE MapperGlyphScalar
////
vtkm::rendering::MapperGlyphScalar mapper;
mapper.SetGlyphType(vtkm::rendering::GlyphType::Cube);
mapper.SetScaleByValue(true);
mapper.SetScaleDelta(10.0f);
vtkm::rendering::View3D view(scene, mapper, canvas);
////
//// END-EXAMPLE MapperGlyphScalar
////
view.SetBackgroundColor(vtkm::rendering::Color(1.0f, 1.0f, 1.0f));
view.SetForegroundColor(vtkm::rendering::Color(0.0f, 0.0f, 0.0f));
view.Paint();
view.SaveAs("GlyphRendering.ppm");
}
void DoEdgeRender()
{
// Load some data to render
vtkm::cont::DataSet surfaceData;
try
{
vtkm::io::VTKDataSetReader reader(
vtkm::cont::testing::Testing::GetTestDataBasePath() + "unstructured/cow.vtk");
surfaceData = reader.ReadDataSet();
}
catch (vtkm::io::ErrorIO& error)
{
std::cout << "Could not read file:" << std::endl << error.GetMessage() << std::endl;
exit(1);
}
catch (...)
{
throw;
}
// Initialize VTK-m rendering classes
vtkm::rendering::Actor actor(surfaceData.GetCellSet(),
surfaceData.GetCoordinateSystem(),
surfaceData.GetField("RandomPointScalars"));
vtkm::rendering::Scene scene;
scene.AddActor(actor);
vtkm::rendering::CanvasRayTracer canvas(1920, 1080);
////
//// BEGIN-EXAMPLE MapperEdge
////
vtkm::rendering::MapperWireframer mapper;
vtkm::rendering::View3D view(scene, mapper, canvas);
////
//// END-EXAMPLE MapperEdge
////
view.SetBackgroundColor(vtkm::rendering::Color(1.0f, 1.0f, 1.0f));
view.SetForegroundColor(vtkm::rendering::Color(0.0f, 0.0f, 0.0f));
view.Paint();
view.SaveAs("EdgeRendering.png");
}
void DoRender()
{
DoBasicRender();
DoPointRender();
DoEdgeRender();
}
} // anonymous namespace
int GuideExampleRendering(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(DoRender, argc, argv);
}

@ -0,0 +1,392 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#ifdef __APPLE__
// Glut is depricated on apple, but is sticking around for now. Hopefully
// someone will step up and make FreeGlut or OpenGlut compatible. Or perhaps
// we should move to GLFW. For now, just disable the warnings.
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
#include <vtkm/io/VTKDataSetReader.h>
#include <vtkm/rendering/Actor.h>
#include <vtkm/rendering/Camera.h>
#include <vtkm/rendering/CanvasRayTracer.h>
#include <vtkm/rendering/MapperRayTracer.h>
#include <vtkm/rendering/View3D.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/internal/Windows.h>
#ifdef __APPLE__
#include <GLUT/glut.h>
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#include <GL/glut.h>
#endif
namespace
{
vtkm::rendering::View3D* gViewPointer = NULL;
int gButtonState[3] = { GLUT_UP, GLUT_UP, GLUT_UP };
int gMousePositionX;
int gMousePositionY;
bool gNoInteraction;
void DisplayCallback()
{
vtkm::rendering::View3D& view = *gViewPointer;
////
//// BEGIN-EXAMPLE RenderToOpenGL
////
view.Paint();
// Get the color buffer containing the rendered image.
vtkm::cont::ArrayHandle<vtkm::Vec4f_32> colorBuffer =
view.GetCanvas().GetColorBuffer();
// Pull the C array out of the arrayhandle.
const void* colorArray =
vtkm::cont::ArrayHandleBasic<vtkm::Vec4f_32>(colorBuffer).GetReadPointer();
// Write the C array to an OpenGL buffer.
glDrawPixels((GLint)view.GetCanvas().GetWidth(),
(GLint)view.GetCanvas().GetHeight(),
GL_RGBA,
GL_FLOAT,
colorArray);
// Swap the OpenGL buffers (system dependent).
////
//// END-EXAMPLE RenderToOpenGL
////
glutSwapBuffers();
if (gNoInteraction)
{
delete gViewPointer;
gViewPointer = NULL;
exit(0);
}
}
void WindowReshapeCallback(int width, int height)
{
gViewPointer->GetCanvas().ResizeBuffers(width, height);
}
void MouseButtonCallback(int buttonIndex, int state, int x, int y)
{
gButtonState[buttonIndex] = state;
gMousePositionX = x;
gMousePositionY = y;
}
////
//// BEGIN-EXAMPLE MouseRotate
////
void DoMouseRotate(vtkm::rendering::View& view,
vtkm::Id mouseStartX,
vtkm::Id mouseStartY,
vtkm::Id mouseEndX,
vtkm::Id mouseEndY)
{
vtkm::Id screenWidth = view.GetCanvas().GetWidth();
vtkm::Id screenHeight = view.GetCanvas().GetHeight();
// Convert the mouse position coordinates, given in pixels from 0 to
// width/height, to normalized screen coordinates from -1 to 1. Note that y
// screen coordinates are usually given from the top down whereas our
// geometry transforms are given from bottom up, so you have to reverse the y
// coordiantes.
vtkm::Float32 startX = (2.0f * mouseStartX) / screenWidth - 1.0f;
vtkm::Float32 startY = -((2.0f * mouseStartY) / screenHeight - 1.0f);
vtkm::Float32 endX = (2.0f * mouseEndX) / screenWidth - 1.0f;
vtkm::Float32 endY = -((2.0f * mouseEndY) / screenHeight - 1.0f);
view.GetCamera().TrackballRotate(startX, startY, endX, endY);
}
////
//// END-EXAMPLE MouseRotate
////
////
//// BEGIN-EXAMPLE MousePan
////
void DoMousePan(vtkm::rendering::View& view,
vtkm::Id mouseStartX,
vtkm::Id mouseStartY,
vtkm::Id mouseEndX,
vtkm::Id mouseEndY)
{
vtkm::Id screenWidth = view.GetCanvas().GetWidth();
vtkm::Id screenHeight = view.GetCanvas().GetHeight();
// Convert the mouse position coordinates, given in pixels from 0 to
// width/height, to normalized screen coordinates from -1 to 1. Note that y
// screen coordinates are usually given from the top down whereas our
// geometry transforms are given from bottom up, so you have to reverse the y
// coordiantes.
vtkm::Float32 startX = (2.0f * mouseStartX) / screenWidth - 1.0f;
vtkm::Float32 startY = -((2.0f * mouseStartY) / screenHeight - 1.0f);
vtkm::Float32 endX = (2.0f * mouseEndX) / screenWidth - 1.0f;
vtkm::Float32 endY = -((2.0f * mouseEndY) / screenHeight - 1.0f);
vtkm::Float32 deltaX = endX - startX;
vtkm::Float32 deltaY = endY - startY;
////
//// BEGIN-EXAMPLE Pan
////
view.GetCamera().Pan(deltaX, deltaY);
////
//// END-EXAMPLE Pan
////
}
////
//// END-EXAMPLE MousePan
////
////
//// BEGIN-EXAMPLE MouseZoom
////
void DoMouseZoom(vtkm::rendering::View& view, vtkm::Id mouseStartY, vtkm::Id mouseEndY)
{
vtkm::Id screenHeight = view.GetCanvas().GetHeight();
// Convert the mouse position coordinates, given in pixels from 0 to height,
// to normalized screen coordinates from -1 to 1. Note that y screen
// coordinates are usually given from the top down whereas our geometry
// transforms are given from bottom up, so you have to reverse the y
// coordiantes.
vtkm::Float32 startY = -((2.0f * mouseStartY) / screenHeight - 1.0f);
vtkm::Float32 endY = -((2.0f * mouseEndY) / screenHeight - 1.0f);
vtkm::Float32 zoomFactor = endY - startY;
////
//// BEGIN-EXAMPLE Zoom
////
view.GetCamera().Zoom(zoomFactor);
////
//// END-EXAMPLE Zoom
////
}
////
//// END-EXAMPLE MouseZoom
////
void MouseMoveCallback(int x, int y)
{
if (gButtonState[0] == GLUT_DOWN)
{
DoMouseRotate(*gViewPointer, gMousePositionX, gMousePositionY, x, y);
}
else if (gButtonState[1] == GLUT_DOWN)
{
DoMousePan(*gViewPointer, gMousePositionX, gMousePositionY, x, y);
}
else if (gButtonState[2] == GLUT_DOWN)
{
DoMouseZoom(*gViewPointer, gMousePositionY, y);
}
gMousePositionX = x;
gMousePositionY = y;
glutPostRedisplay();
}
void SaveImage()
{
std::cout << "Saving image." << std::endl;
vtkm::rendering::Canvas& canvas = gViewPointer->GetCanvas();
////
//// BEGIN-EXAMPLE SaveCanvasImage
////
canvas.SaveAs("MyVis.ppm");
////
//// END-EXAMPLE SaveCanvasImage
////
}
////
//// BEGIN-EXAMPLE ResetCamera
////
void ResetCamera(vtkm::rendering::View& view)
{
vtkm::Bounds bounds = view.GetScene().GetSpatialBounds();
view.GetCamera().ResetToBounds(bounds);
//// PAUSE-EXAMPLE
std::cout << "Position: " << view.GetCamera().GetPosition() << std::endl;
std::cout << "LookAt: " << view.GetCamera().GetLookAt() << std::endl;
std::cout << "ViewUp: " << view.GetCamera().GetViewUp() << std::endl;
std::cout << "FOV: " << view.GetCamera().GetFieldOfView() << std::endl;
std::cout << "ClipRange: " << view.GetCamera().GetClippingRange() << std::endl;
//// RESUME-EXAMPLE
}
////
//// END-EXAMPLE ResetCamera
////
void ChangeCamera(vtkm::rendering::Camera& camera)
{
// Just set some camera parameters for demonstration purposes.
////
//// BEGIN-EXAMPLE CameraPositionOrientation
////
camera.SetPosition(vtkm::make_Vec(10.0, 6.0, 6.0));
camera.SetLookAt(vtkm::make_Vec(0.0, 0.0, 0.0));
camera.SetViewUp(vtkm::make_Vec(0.0, 1.0, 0.0));
camera.SetFieldOfView(60.0);
camera.SetClippingRange(0.1, 100.0);
////
//// END-EXAMPLE CameraPositionOrientation
////
}
void ObliqueCamera(vtkm::rendering::View& view)
{
////
//// BEGIN-EXAMPLE AxisAlignedCamera
////
view.GetCamera().SetPosition(vtkm::make_Vec(0.0, 0.0, 0.0));
view.GetCamera().SetLookAt(vtkm::make_Vec(0.0, 0.0, -1.0));
view.GetCamera().SetViewUp(vtkm::make_Vec(0.0, 1.0, 0.0));
vtkm::Bounds bounds = view.GetScene().GetSpatialBounds();
view.GetCamera().ResetToBounds(bounds);
////
//// END-EXAMPLE AxisAlignedCamera
////
////
//// BEGIN-EXAMPLE CameraMovement
////
view.GetCamera().Azimuth(45.0);
view.GetCamera().Elevation(45.0);
////
//// END-EXAMPLE CameraMovement
////
}
void KeyPressCallback(unsigned char key, int x, int y)
{
switch (key)
{
case 'q':
case 'Q':
delete gViewPointer;
gViewPointer = NULL;
exit(0);
break;
case 's':
case 'S':
SaveImage();
break;
case 'r':
case 'R':
ResetCamera(*gViewPointer);
break;
case 'c':
case 'C':
ChangeCamera(gViewPointer->GetCamera());
break;
case 'o':
case 'O':
ObliqueCamera(*gViewPointer);
}
glutPostRedisplay();
(void)x;
(void)y;
}
int go()
{
// Initialize VTK-m rendering classes
vtkm::cont::DataSet surfaceData;
try
{
vtkm::io::VTKDataSetReader reader(
vtkm::cont::testing::Testing::GetTestDataBasePath() + "unstructured/cow.vtk");
surfaceData = reader.ReadDataSet();
}
catch (vtkm::io::ErrorIO& error)
{
std::cout << "Could not read file:" << std::endl << error.GetMessage() << std::endl;
exit(1);
}
catch (...)
{
throw;
}
////
//// BEGIN-EXAMPLE SpecifyColorTable
////
vtkm::rendering::Actor actor(surfaceData.GetCellSet(),
surfaceData.GetCoordinateSystem(),
surfaceData.GetField("RandomPointScalars"),
vtkm::cont::ColorTable("inferno"));
////
//// END-EXAMPLE SpecifyColorTable
////
vtkm::rendering::Scene scene;
scene.AddActor(actor);
vtkm::rendering::MapperRayTracer mapper;
vtkm::rendering::CanvasRayTracer canvas;
gViewPointer = new vtkm::rendering::View3D(scene, mapper, canvas);
// Start the GLUT rendering system. This function typically does not return.
glutMainLoop();
return 0;
}
int doMain(int argc, char* argv[])
{
// Initialize GLUT window and callbacks
glutInit(&argc, argv);
glutInitWindowSize(960, 600);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
glutCreateWindow("VTK-m Example");
glutDisplayFunc(DisplayCallback);
glutReshapeFunc(WindowReshapeCallback);
glutMouseFunc(MouseButtonCallback);
glutMotionFunc(MouseMoveCallback);
glutKeyboardFunc(KeyPressCallback);
gNoInteraction = false;
for (int arg = 1; arg < argc; ++arg)
{
if (strcmp(argv[arg], "--no-interaction") == 0)
{
gNoInteraction = true;
}
}
return vtkm::cont::testing::Testing::Run(go, argc, argv);
}
} // anonymous namespace
int GuideExampleRenderingInteractive(int argc, char* argv[])
{
return doMain(argc, argv);
}

@ -0,0 +1,96 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/cont/RuntimeDeviceTracker.h>
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/DeviceAdapterTag.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
static const vtkm::Id ARRAY_SIZE = 10;
void CopyWithRuntime()
{
std::cout << "Checking runtime in copy." << std::endl;
using T = vtkm::Float32;
vtkm::cont::ArrayHandle<T> srcArray;
srcArray.Allocate(ARRAY_SIZE);
SetPortal(srcArray.WritePortal());
vtkm::cont::ArrayHandle<T> destArray;
////
//// BEGIN-EXAMPLE RestrictCopyDevice
////
vtkm::cont::ScopedRuntimeDeviceTracker tracker(
vtkm::cont::DeviceAdapterTagKokkos(), vtkm::cont::RuntimeDeviceTrackerMode::Disable);
////
//// BEGIN-EXAMPLE ArrayCopy
////
vtkm::cont::ArrayCopy(srcArray, destArray);
////
//// END-EXAMPLE ArrayCopy
////
////
//// END-EXAMPLE RestrictCopyDevice
////
VTKM_TEST_ASSERT(destArray.GetNumberOfValues() == ARRAY_SIZE, "Bad array size.");
CheckPortal(destArray.ReadPortal());
}
////
//// BEGIN-EXAMPLE ForceThreadLocalDevice
////
void ChangeDefaultRuntime()
{
std::cout << "Checking changing default runtime." << std::endl;
//// PAUSE-EXAMPLE
#ifdef VTKM_ENABLE_KOKKOS
//// RESUME-EXAMPLE
////
//// BEGIN-EXAMPLE SpecifyDeviceAdapter
////
vtkm::cont::ScopedRuntimeDeviceTracker(vtkm::cont::DeviceAdapterTagKokkos{});
////
//// END-EXAMPLE SpecifyDeviceAdapter
////
//// PAUSE-EXAMPLE
#endif //VTKM_ENABLE_KOKKOS
//// RESUME-EXAMPLE
// VTK-m operations limited to Kokkos devices here...
// Devices restored as we leave scope.
}
////
//// END-EXAMPLE ForceThreadLocalDevice
////
void Run()
{
CopyWithRuntime();
ChangeDefaultRuntime();
}
} // anonymous namespace
int GuideExampleRuntimeDeviceTracker(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(Run, argc, argv);
}

@ -0,0 +1,61 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/filter/field_transform/PointElevation.h>
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
void DoTiming()
{
vtkm::cont::DataSet dataSet =
vtkm::cont::testing::MakeTestDataSet().Make2DUniformDataSet0();
////
//// BEGIN-EXAMPLE Timer
////
vtkm::filter::field_transform::PointElevation elevationFilter;
elevationFilter.SetUseCoordinateSystemAsField(true);
elevationFilter.SetOutputFieldName("elevation");
vtkm::cont::Timer timer;
timer.Start();
vtkm::cont::DataSet result = elevationFilter.Execute(dataSet);
// This code makes sure data is pulled back to the host in a host/device
// architecture.
vtkm::cont::ArrayHandle<vtkm::Float64> outArray;
result.GetField("elevation").GetData().AsArrayHandle(outArray);
outArray.SyncControlArray();
timer.Stop();
vtkm::Float64 elapsedTime = timer.GetElapsedTime();
std::cout << "Time to run: " << elapsedTime << std::endl;
////
//// END-EXAMPLE Timer
////
}
} // anonymous namespace
int GuideExampleTimer(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(DoTiming, argc, argv);
}

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6b5c80dac2e4c3769231c0e0b2a547e1699403c131edcf89738b436f7471366d
size 234301

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d20c5d53b1a110a432d498e2265e82112ca12f4aa3565f0fe6e27d48d833dca9
size 135748

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:10b421758c721d05233205327ee49c6f568e4fedd22c2a54dd1ad10584d5e4fb
size 57467

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:438aacdfe49160475b89062562888b43bf1fd9a5edfe5ee8e2985042ca96c69a
size 223324

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4cbad6050396e9d7b48197623f15dc67c0e3747a048ae832a51ba2942e0dd2bd
size 763001

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:deaf122e7e75793fa5208879c498956cdd209a5cfee5993f9a79072065816aa4
size 198679

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:758d560cc3a5a0f8a88b99a75ca520fdf647d3e3cd47e456e974a89e19236604
size 564707

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:02742a55f4c598880bbab3baa419c5a20adf5fafb3ca4cc2a6a06adbdfc00007
size 306743

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c934f1896ffd881ce13032430e7dfeb06cbfaad2cbc9a69e44537e108f914657
size 603105

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e70c2d8d0341c92c0d18286a40fdd97aff810adbc0e99d2f0881bf9c7683c4a3
size 378456

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a6fce241ace6a4faaf0e46094b8ef3b568e680d6f50c4224ac89d4bb80d8e001
size 288203

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:cf05b1fda263a8d50c4b4d93ae43759da942545156916950889b9fa5e1c67232
size 207691

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:98cbe014e742412d88ed967d4ad4b1093c37de99ffa594ff23bd999a8e24741b
size 158297

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:78ed51a7b522f4872a58b182c14bb53538b48bdaaf874fd3d6bdc48ab41b90a0
size 131030

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6ab854e2fa0874127cc096790829ba4a3c5f388cacee1813bb1c348385352b76
size 10758

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:723804fe5e3fc6daa97856a6762d9d161247893ec3469f2618bc9a9f85528035
size 83974

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1347eb5bde17e0d9946e32b7107b07395d014d65c27f16a5e2576506434835e7
size 2332

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:664d14e73d941bf3ad67e5ceb3099f802fa464171ecbe533c97af7739643d01b
size 6570

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:924763fffb9cdf77dd2cc25af168a9fd26641d338ad41d885a90f023e80709c7
size 4188

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:51c93c35c3422f07b4a1d7b066f63e99c74f6b0a40595201ef12a324faf53b41
size 829249

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8b212bde9e1e897fa5540d5a2075c93186f2e6a165cbb8dd125dbd1a8e49d3e0
size 6286

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4b89bee998fd641b46a9f911273503721f53dcf0bbdd3992f332bcc0316f5192
size 832940

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ecefed13142acc7a0927e6d24d34943c1213deb98536e537b7cc9be7b0842323
size 9077

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6b51389f747abcf666f3eba96dafb38b7a28ab2550965ad9491b85f3563f9748
size 126197

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e7fa527d2a13537141deb41e7ea2d3f6b63d47d835b6272e9c14592d7a5045e5
size 4855

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:efb3295e684186725074e48b9f2e9009e278cdcd2c837c3a64f0814abef5f22f
size 125623

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f2a0ca582ac6b1ba633fbfb62eebace76bc156879dfd6012409b527bcd1ea179
size 6908

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8b3ffed9b57b75524f2f57d864c901d461b249821c02d4f3cfd819ec6701571f
size 113562

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:52926a39db6c0f1a8647be9789ae8252241f9e7e52b947dfba95a6c5a0c5beac
size 4772

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:de1efcb86cdbbd924b9cf4dc2da21920cdd5fe5b6382486c645b1185576fe704
size 98229

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:aac7917e99e44f20ac8b5b769501c7d76015b01ee566690237d451f3a81054c4
size 803

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:21fa8578a661a18bcaf0921bc49a46b2aaaa8534045c35dd3135bb438953f933
size 127567

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b49462de9defbe8696f567b800b439c16050f0e25060ee2ecc8fad50b3c81d80
size 10329

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7b4befa54d65fa91351e9b2c6b68da2a2667148afe06b418313e04837996501f
size 99997

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f2e0418bfb7913e12f16b684864d436ee32e90455a2185699738715996395f25
size 9772

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4d97509cacd71b30c41b304205751f1b63a217d10c22c9940fb09caba623b844
size 139916

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c40c66cb5b873b93e69ff71bad390f614c3a610f354ff7c29561f8e9852719a8
size 77162

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:32708956f822d32f13b91d7f703588e796c720b1d465f6c4758acf9ab1adbe0b
size 71423

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:443589bb56a3d1e0a066b2f4964e09e80b88fc97bb79188b6b007616a11c87c5
size 93821

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b3013a10ac982aa08e062d3035c12b7a30b2a023005f37ec1a612234981b42d5
size 42385

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:18a9c8563a09528ca083e0dac9e57c742c57c2a46bdb179e54b4256278b86851
size 102156

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f73ed769039f1509f645bde7f7f54b6db3418eb9055e814d7254bb2457a8e3ce
size 87978

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:deac6d7e7f164bc5f1b0de284dafc895cc5f455dc4a58aacd96689b499302744
size 26621

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a7f4e0f22c842130c928d1a9d838d2c6bdc21d06ea6bf55067784dd73c1f7702
size 143355

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a1fee1ef5c9f02fefcc0507fa4185742997f45d02af111c515e327a26568ae25
size 837224

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d66abf7fd51769ad196e5bb0a4eaa33c5f4904d4d1924ad45f172753136ced72
size 58627

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:97d3e9bfc03759ab572c4b1ad711c8a0f5f6a20021f011ef6263ba9bd960142f
size 710

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:de2e3b9772eaaec8c699d97380eaea681ffd70680a584b956a4fec1d65f06685
size 710

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:13096ab8a6e32567f1a6d8deaec017a29f9218b2e46c186e185bcfc79dceb7e1
size 710

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3cacb8997486c98f1cd7fc9b3e0bb6e06c5dba55b3ea48b37b9297a666acae77
size 710

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f0e3e25b3c2a93c84d026ae06c5e393c7fef58327d05ffc22746db2c4e59c658
size 710

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:76021841fdc1c4c1d32b79cffd834b0eead0b85716ac486d7602d922407a91f0
size 710

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:11cfb6b9267fee3bb2f3e1b07bcb43b1105d8c68b6ae8605719f8e48e582dc27
size 710

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e3c8b2ba6bd8639fc4f5b8ba50c743567a4acaaa66a4be8421f36a8a0545daa5
size 710

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ecfe7e948e186cf0b436c3bf38cd7ee19ab61fc4c5619517d0c5e883e93e74c5
size 710

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:162964095a43d62297824ba398acc5588af374c4c23c8fe702630954157cc202
size 710

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3eec2a47ca94682bd4fcb00b9119c93f5fe27393fd89c3cc6dbc609f8467c3a8
size 710

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c4968a413aa94ae33904eb4850115bae0cb451c87fa6c32e235ff1bdf4a8253d
size 710

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a2ff1a172ab843948e6df0d8c01e4ca64b2255e3a16c1c78da23d3d99f6dada2
size 710

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ca734ced93f979f6da689712865c1529f6be4eff61ade50ee633b76d9321a783
size 710

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ebc251a5676c6d9e85d49521b3cd1062223c58b6e6823b84ad85d9d0500c6225
size 710

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e3c8b2ba6bd8639fc4f5b8ba50c743567a4acaaa66a4be8421f36a8a0545daa5
size 710

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0d1874a353f071bad1f3a53789daabd001e6e26393f9194db7c2377a116a01b5
size 114

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:56044dca0b9521811a8c2947eaf13d63960e1b597ce33c2cea024efe753cc83a
size 710

@ -0,0 +1,167 @@
==============================
Implicit Functions
==============================
.. index:: implicit function
.. index:: functions; implicit
|VTKm|'s implicit functions are objects that are constructed with values representing 3D spatial coordinates that often describe a shape.
Each implicit function is typically defined by the surface formed where the value of the function is equal to 0.
All implicit functions implement ``Value()`` and ``Gradient()`` methods that describe the orientation of a provided point with respect to the implicit function's shape.
The ``Value()`` method for an implicit function takes a :type:`vtkm::Vec3f` and returns a :type:`vtkm::FloatDefault` representing the orientation of the point with respect to the implicit function's shape.
Negative scalar values represent vector points inside of the implicit function's shape.
Positive scalar values represent vector points outside the implicit function's shape.
Zero values represent vector points that lie on the surface of the implicit function.
The ``Gradient()`` method for an implicit function takes a :type:`vtkm::Vec3f` and returns a :type:`vtkm::Vec3f` representing the pointing direction from the implicit function's shape.
Gradient calculations are more object shape specific.
It is advised to look at the individual shape implementations for specific implicit functions.
Implicit functions are useful when trying to clip regions from a dataset.
For example, it is possible to use :class:`vtkm::filter::contour::ClipWithImplicitFunction` to remove a region in a provided dataset according to the shape of an implicit function.
See :secref:`provided-filters:Clip with Implicit Function` for more information on clipping with implicit functions.
|VTKm| has implementations of various implicit functions provided by the following subclasses.
------------------------------
Plane
------------------------------
.. index::
double: implicit function; plane
:class:`vtkm::Plane` defines an infinite plane.
The plane is defined by a pair of :type:`vtkm::Vec3f` values that represent the origin, which is any point on the plane, and a normal, which is a vector that is tangent to the plane.
These are set with the :func:`vtkm::Plane::SetOrigin` and :func:`vtkm::Plane::SetNormal` methods, respectively.
Planes extend infinitely from the origin point in the direction perpendicular form the Normal.
An example :class:`vtkm::Plane` is shown in :numref:`fig:ImplicitPlane`.
.. figure:: images/ImplicitPlane.png
:width: 2.5in
:name: fig:ImplicitPlane
Visual Representation of an Implicit Plane.
The red dot and arrow represent the origin and normal of the plane, respectively.
For demonstrative purposes the plane as shown with limited area, but in actuality the plane extends infinitely.
.. doxygenclass:: vtkm::Plane
:members:
------------------------------
Sphere
------------------------------
.. index::
double: implicit function; sphere
:class:`vtkm::Sphere` defines a sphere.
The :class:`vtkm::Sphere` is defined by a center location and a radius, which are set with the :func:`vtkm::Sphere::SetCenter` and :func:`vtkm::Sphere::SetRadius` methods, respectively.
An example :class:`vtkm::Sphere` is shown in :numref:`fig:ImplicitSphere`.
.. figure:: images/ImplicitSphere.png
:width: width=2.5in
:name: fig:ImplicitSphere
Visual Representation of an Implicit Sphere.
The red dot represents the center of the sphere.
The radius is the length of any line (like the blue one shown here) that extends from the center in any direction to the surface.
.. doxygenclass:: vtkm::Sphere
:members:
------------------------------
Cylinder
------------------------------
.. index::
double: implicit function; cylinder
:class:`vtkm::Cylinder` defines a cylinder that extends infinitely along its axis.
The cylinder is defined with a center point, a direction of the center axis, and a radius, which are set with :func:`vtkm::Cylinder::SetCenter`, :func:`vtkm::Cylinder::SetAxis`, and :func:`vtkm::Cylinder::SetRadius`, respectively.
An example :class:`vtkm::Cylinder` is shown in :numref:`fig:ImplicitCylinder` with set origin, radius, and axis values.
.. figure:: images/ImplicitCylinder.png
:width: 2.5in
:name: fig:ImplicitCylinder
Visual Representation of an Implicit Cylinder.
The red dot represents the center value, and the red arrow represents the vector that points in the direction of the axis.
The radius is the length of any line (like the blue one shown here) that extends perpendicular from the axis to the surface.
.. doxygenclass:: vtkm::Cylinder
:members:
------------------------------
Box
------------------------------
.. index::
double:: implicit function; box
:class:`vtkm::Box` defines an axis-aligned box.
The box is defined with a pair of :type:`vtkm::Vec3f` values that represent the minimum point coordinates and maximum point coordinates, which are set with :func:`vtkm::Box::SetMinPoint` and :func:`vtkm::Box::SetMaxPoint`, respectively.
The :class:`vtkm::Box` is the shape enclosed by intersecting axis-parallel lines drawn from each point.
Alternately, the :class:`vtkm::Box` can be specified with a :class:`vtkm::Bounds` object using the :func:`vtkm::Box::SetBounds` method.
An example :class:`vtkm::Box` is shown in :numref:`fig:ImplicitBox`.
.. figure:: images/ImplicitBox.png
:width: 2.5in
:name: fig:ImplicitBox
Visual Representation of an Implicit Box.
The red dots represent the minimum and maximum points.
.. doxygenclass:: vtkm::Box
:members:
------------------------------
Frustum
------------------------------
.. index::
double: implicit function; frustum
:class:`vtkm::Frustum` defines a hexahedral region with potentially oblique faces.
A :class:`vtkm::Frustum` is typically used to define the tapered region of space visible in a perspective camera projection.
The frustum is defined by the 6 planes that make up its 6 faces.
Each plane is defined by a point and a normal vector, which are set with :func:`vtkm::Frustum::SetPlane` and :func:`vtkm::Frustum::SetNormal`, respectively.
Parameters for all 6 planes can be set at once using the :func:`vtkm::Frustum::SetPlanes` and :func:`vtkm::Frustum::SetNormals` methods.
Alternately, the :class:`vtkm::Frustum` can be defined by the 8 points at the vertices of the enclosing hexahedron using the :func:`vtkm::Frustum::CreateFromPoints` method.
The points given to :func:`vtkm::Frustum::CreateFromPoints` must be in hex-cell order where the first four points are assumed to be a plane, and the last four points are assumed to be a plane.
An example :class:`vtkm::Frustum` is shown in :numref:`fig:ImplicitFrustum`.
.. figure:: images/ImplicitFrustum.png
:width: 2.5in
:name: fig:ImplicitFrustum
Visual Representation of an Implicit Frustum.
The red dots and arrows represent the points and normals defining each enclosing plane.
The blue dots represent the 8 vertices, which can also be used to define the frustum.
.. doxygenclass:: vtkm::Frustum
------------------------------
General Implicit Functions
------------------------------
.. index::
double: implicit function; general
It is often the case when creating code that uses an implicit function that you do not know which implicit function will be desired.
For example, the :class:`vtkm::filter::contour::ClipWithImplicitFunction` filter can be used with any of the implicit functions described here (:class:`vtkm::Plane`, :class:`vtkm::Sphere`, etc.).
To handle conditions where you want to support multiple implicit functions simultaneously, |VTKm| provides :class:`vtkm::ImplicitFunctionGeneral`.
Any of the implicit functions described in this chapter can be copied to a :class:`vtkm::ImplicitFunctionGeneral`, which will behave like the specified function.
The following example shows shows passing a :class:`vtkm::Sphere` to :class:`vtkm::filter::contour::ClipWithImplicitFunction`, which internally uses :class:`vtkm::ImplicitFunctionGeneral` to manage the implicit function types.
.. load-example:: ImplicitFunctionGeneral
:file: GuideExampleProvidedFilters.cxx
:caption: Passing an implicit function to a filter.
.. doxygenclass:: vtkm::ImplicitFunctionGeneral
:members:

@ -0,0 +1,35 @@
==============================
Initialization
==============================
.. index:: initialization
When it comes to running |VTKm| code, there are a few ways in which various facilities, such as logging device connections, and device configuration parameters, can be initialized.
The preferred method of initializing these features is to run the :func:`vtkm::cont::Initialize` function.
Although it is not strictly necessary to call :func:`vtkm::cont::Initialize`, it is recommended to set up state and check for available devices.
.. doxygenfunction:: vtkm::cont::Initialize(int &argc, char *argv[], InitializeOptions opts)
.. index::
single: argc
single: argv
:func:`vtkm::cont::Initialize` can be called without any arguments, in which case |VTKm| will be initialized with defaults.
But it can also optionally take the ``argc`` and ``argv`` arguments to the ``main`` function to parse some options that control the state of |VTKm|.
|VTKm| accepts arguments that, for example, configure the compute device to use or establish logging levels.
Any arguments that are handled by |VTKm| are removed from the ``argc``/``argv`` list so that your program can then respond to the remaining arguments.
:func:`vtkm::cont::Initialize` returns a :struct:`vtkm::cont::InitializeResult` structure.
This structure contains information about the supported arguments and options selected during initialization.
.. doxygenstruct:: vtkm::cont::InitializeResult
:members:
:func:`vtkm::cont::Initialize` takes an optional third argument that specifies some options on the behavior of the argument parsing.
The options are specified as a bit-wise "or" of fields specified in the :enum:`vtkm::cont::InitializeOptions` enum.
.. doxygenenum:: vtkm::cont::InitializeOptions
.. load-example:: BasicInitialize
:file: GuideExampleInitialization.cxx
:caption: Calling :func:`vtkm::cont::Initialize`.

143
docs/users-guide/io.rst Normal file

@ -0,0 +1,143 @@
==============================
File I/O
==============================
.. index::
single: I/O
single: file I/O
Before |VTKm| can be used to process data, data need to be loaded into the
system.
|VTKm| comes with a basic file I/O package to get started developing very
quickly.
All the file I/O classes are declared under the ``vtkm::io`` namespace.
.. didyouknow::
Files are just one of many ways to get data in and out of |VTKm|.
In later chapters we explore ways to define |VTKm| data structures of
increasing power and complexity.
In particular, :secref:`dataset:Building Data Sets` describes how to build |VTKm| data set objects and Section \ref{sec:ArrayHandle:Adapting} documents how to adapt data structures defined in other libraries to be used directly in |VTKm|.
.. todo:: Add ArrayHandle section reference above.
------------------------------
Readers
------------------------------
.. index::
single: file I/O; read
single: read file
All reader classes provided by |VTKm| are located in the ``vtkm::io``
namespace.
The general interface for each reader class is to accept a filename in the constructor and to provide a ``ReadDataSet`` method to load the data from disk.
The data in the file are returned in a :class:`vtkm::cont::DataSet` object
as described in :chapref:`dataset:Data Sets`, but it is sufficient to know that a ``DataSet`` can be passed among readers, writers, filters, and rendering units.
Legacy VTK File Reader
==============================
Legacy VTK files are a simple open format for storing visualization data.
These files typically have a :file:`.vtk` extension.
Legacy VTK files are popular because they are simple to create and read and
are consequently supported by a large number of tools.
The format of legacy VTK files is well documented in *The VTK User's
Guide* [as well as online](https://examples.vtk.org/site/VTKFileFormats/).
Legacy VTK files can also be read and written with tools like ParaView and VisIt.
Legacy VTK files can be read using the :class:`vtkm::io::VTKDataSetReader` class.
.. doxygenclass:: vtkm::io::VTKDataSetReader
:members:
.. load-example:: VTKDataSetReader
:file: GuideExampleIO.cxx
:caption: Reading a legacy VTK file.
Image Readers
==============================
|VTKm| provides classes to read images from some standard image formats.
These readers will store the data in a :class:`vtkm::cont::DataSet` object with the colors stored as a named point field.
The colors are read as 4-component RGBA vectors for each pixel.
Each component in the pixel color is stored as a 32-bit float between 0 and 1.
Portable Network Graphics (PNG) files can be read using the :class:`vtkm::io::ImageReaderPNG` class.
.. doxygenclass:: vtkm::io::ImageReaderPNG
:members:
.. load-example:: ImageReaderPNG
:file: GuideExampleIO.cxx
:caption: Reading an image from a PNG file.
Portable anymap (PNM) files can be read using the :class:`vtkm::io::ImageReaderPNM` class.
.. doxygenclass:: vtkm::io::ImageReaderPNM
:members:
Like for PNG files, a :class:`vtkm::io::ImageReaderPNM` is constructed with the name of the file to read from.
.. load-example:: ImageReaderPNM
:file: GuideExampleIO.cxx
:caption: Reading an image from a PNM file.
------------------------------
Writers
------------------------------
.. index::
single: file I/O; write
single: write file
All writer classes provided by |VTKm| are located in the ``vtkm::io`` namespace.
The general interface for each writer class is to accept a filename in the constructor and to provide a ``WriteDataSet`` method to save data to the disk.
The ``WriteDataSet`` method takes a :class:`vtkm::cont::DataSet` object as an argument, which contains the data to write to the file.
Legacy VTK File Writer
==============================
Legacy VTK files can be written using the :class:`vtkm::io::VTKDataSetWriter` class.
.. doxygenclass:: vtkm::io::VTKDataSetWriter
:members:
.. doxygenenum:: vtkm::io::FileType
.. load-example:: VTKDataSetWriter
:file: GuideExampleIO.cxx
:caption: Writing a legacy VTK file.
Image Writers
==============================
|VTKm| provides classes to some standard image formats.
These writers store data in a :class:`vtkm::cont::DataSet`.
The data must be a 2D structure with the colors stored in a point field.
(See :chapref:`dataset:Data Sets` for details on :class:`vtkm::cont::DataSet` objects.)
Portable Network Graphics (PNG) files can be written using the :class:`vtkm::io::ImageWriterPNG` class.
.. doxygenclass:: vtkm::io::ImageWriterPNG
:members:
By default, PNG files are written as RGBA colors using 8-bits for each component.
You can change the format written using the :func:`vtkm::io::ImageWriterPNG::SetPixelDepth` method.
This takes an item in the :enum:`vtkm::io::ImageWriterPNG::PixelDepth` enumeration.
.. doxygenenum:: vtkm::io::ImageWriterBase::PixelDepth
.. load-example:: ImageWriterPNG
:file: GuideExampleIO.cxx
:caption: Writing an image to a PNG file.
Portable anymap (PNM) files can be written using the :class:`vtkm::io::ImageWriterPNM` class.
.. doxygenclass:: vtkm::io::ImageWriterPNM
:members:
.. load-example:: ImageWriterPNM
:file: GuideExampleIO.cxx
:caption: Writing an image to a PNM file.

@ -0,0 +1,167 @@
==============================
Managing Devices
==============================
Multiple vendors vie to provide accelerator-type processors.
|VTKm| endeavors to support as many such architectures as possible.
Each device and device technology requires some level of code specialization, and that specialization is encapsulated in a unit called a :index:`device adapter`.
So far in :partref:`part-using:Using |VTKm|` we have been writing code that runs on a local serial CPU.
In those examples where we run a filter, |VTKm| is launching parallel execution in the execution environment.
Internally |VTKm| uses a device adapter to manage this execution.
A build of |VTKm| generally supports multiple device adapters.
In this chapter we describe how to represent and manage devices.
------------------------------
Device Adapter Tag
------------------------------
.. index::
double: device adapter; tag
A device adapter is identified by a *device adapter tag*.
This tag, which is simply an empty struct type, is used as the template parameter for several classes in the |VTKm| control environment and causes these classes to direct their work to a particular device.
The following device adapter tags are available in |VTKm|.
.. index:: serial
.. doxygenstruct:: vtkm::cont::DeviceAdapterTagSerial
.. index:: cuda
.. doxygenstruct:: vtkm::cont::DeviceAdapterTagCuda
.. index:: OpenMP
.. doxygenstruct:: vtkm::cont::DeviceAdapterTagOpenMP
.. index:: Intel Threading Building Blocks
.. index:: TBB
.. doxygenstruct:: vtkm::cont::DeviceAdapterTagTBB
.. index:: Kokkos
.. doxygenstruct:: vtkm::cont::DeviceAdapterTagKokkos
The following example uses the tag for the Kokkos device adapter to specify a specific device for |VTKm| to use.
(Details on specifying devices in |VTKm| is provided in :secref:`managing-devices:Specifying Devices`.)
.. load-example:: SpecifyDeviceAdapter
:file: GuideExampleRuntimeDeviceTracker.cxx
:caption: Specifying a device using a device adapter tag.
For classes and methods that have a template argument that is expected to be a device adapter tag, the tag type can be checked with the :c:macro:`VTKM_IS_DEVICE_ADAPTER_TAG` macro to verify the type is a valid device adapter tag.
It is good practice to check unknown types with this macro to prevent further unexpected errors.
..
Functions, methods, and classes that directly use device adapter tags are usually templated on the device adapter tag.
This allows the function or class to be applied to any type of device specified at compile time.
.. load-example:: DeviceTemplateArg
:file: GuideExampleRuntimeDeviceTracker.cxx
:caption: Specifying a device using template parameters.
.. commonerrors::
A device adapter tag is a class just like every other type in C++.
Thus it is possible to accidently use a type that is not a device adapter tag when one is expected as a template argument.
This leads to unexpected errors in strange parts of the code.
To help identify these errors, it is good practice to use the :c:macro:`VTKM_IS_DEVICE_ADAPTER_TAG` macro to verify the type is a valid device adapter tag.
:numref:`ex:DeviceTemplateArg` uses this macro on line 4.
------------------------------
Device Adapter Id
------------------------------
.. index::
double: device adapter; id
Using a device adapter tag directly means that the type of device needs to be known at compile time.
To store a device adapter type at run time, one can instead use :struct:`vtkm::cont::DeviceAdapterId`.
:struct:`vtkm::cont::DeviceAdapterId` is a superclass to all the device adapter tags, and any device adapter tag can be "stored" in a :struct:`vtkm::cont::DeviceAdapterId`.
Thus, it is more common for functions and classes to use :struct:`vtkm::cont::DeviceAdapterId` then to try to track a specific device with templated code.
.. doxygenstruct:: vtkm::cont::DeviceAdapterId
:members:
.. didyouknow::
As a cheat, all device adapter tags actually inherit from the :struct:`vtkm::cont::DeviceAdapterId` class.
Thus, all of these methods can be called directly on a device adapter tag.
.. commonerrors::
Just because the :func:`vtkm::cont::DeviceAdapterId::IsValueValid` returns true that does not necessarily mean that this device is available to be run on.
It simply means that the device is implemented in |VTKm|.
However, that device might not be compiled, or that device might not be available on the current running system, or that device might not be enabled.
Use the device runtime tracker described in :secref:`managing-devices:Runtime Device Tracker` to determine if a particular device can actually be used.
In addition to the provided device adapter tags listed previously, a :struct:`vtkm::cont::DeviceAdapterId` can store some special device adapter tags that do not directly specify a specific device.
.. index:: device adapter; any
.. doxygenstruct:: vtkm::cont::DeviceAdapterTagAny
.. index:: device adapter; undefined
.. doxygenstruct:: vtkm::cont::DeviceAdapterTagUndefined
.. didyouknow::
Any device adapter tag can be used where a device adapter id is expected.
Thus, you can use a device adapter tag whenever you want to specify a particular device and pass that to any method expecting a device id.
Likewise, it is usually more convenient for classes and methods to manage device adapter ids rather than device adapter tag.
------------------------------
Runtime Device Tracker
------------------------------
.. index::
single: runtime device tracker
single: device adapter; runtime tracker
It is often the case that you are agnostic about what device |VTKm| algorithms run so long as they complete correctly and as fast as possible.
Thus, rather than directly specify a device adapter, you would like |VTKm| to try using the best available device, and if that does not work try a different device.
Because of this, there are many features in |VTKm| that behave this way.
For example, you may have noticed that running filters, as in the examples of :chapref:`running-filters:Running Filters`, you do not need to specify a device; they choose a device for you.
However, even though we often would like |VTKm| to choose a device for us, we still need a way to manage device preferences.
|VTKm| also needs a mechanism to record runtime information about what devices are available so that it does not have to continually try (and fail) to use devices that are not available at runtime.
These needs are met with the :class:`vtkm::cont::RuntimeDeviceTracker` class.
:class:`vtkm::cont::RuntimeDeviceTracker` maintains information about which devices can and should be run on.
|VTKm| maintains a :class:`vtkm::cont::RuntimeDeviceTracker` for each thread your code is operating on.
To get the runtime device for the current thread, use the :func:`vtkm::cont::GetRuntimeDeviceTracker` method.
.. doxygenfunction:: vtkm::cont::GetRuntimeDeviceTracker
.. doxygenclass:: vtkm::cont::RuntimeDeviceTracker
:members:
.. index::
single: runtime device tracker; scoped
single: device adapter; scoped runtime tracker
single: scoped device adapter
------------------------------
Specifying Devices
------------------------------
A :class:`vtkm::cont::RuntimeDeviceTracker` can be used to specify which devices to consider for a particular operation.
However, a better way to specify devices is to use the :class:`vtkm::cont::ScopedRuntimeDeviceTracker` class.
When a :class:`vtkm::cont::ScopedRuntimeDeviceTracker` is constructed, it specifies a new set of devices for |VTKm| to use.
When the :class:`vtkm::cont::ScopedRuntimeDeviceTracker` is destroyed as it leaves scope, it restores |VTKm|'s devices to those that existed when it was created.
.. doxygenclass:: vtkm::cont::ScopedRuntimeDeviceTracker
:members:
The following example demonstrates how the :class:`vtkm::cont::ScopedRuntimeDeviceTracker` is used to force the |VTKm| operations that happen within a function to operate exclusively with the Kokkos device.
.. load-example:: ForceThreadLocalDevice
:file: GuideExampleRuntimeDeviceTracker.cxx
:caption: Restricting which devices |VTKm| uses per thread.
In the previous example we forced |VTKm| to use the Kokkos device.
This is the default behavior of :class:`vtkm::cont::ScopedRuntimeDeviceTracker`, but the constructor takes an optional second argument that is a value in the :enum:`vtkm::cont::RuntimeDeviceTrackerMode` to specify how modify the current device adapter list.
.. doxygenenum:: RuntimeDeviceTrackerMode
As a motivating example, let us say that we want to perform a deep copy of an array (described in Section~\ref{sec:DeepArrayCopies}).
However, we do not want to do the copy on a Kokkos device because we happen to know the data is not on that device and we do not want to spend the time to transfer the data to that device.
We can use a :class:`vtkm::cont::ScopedRuntimeDeviceTracker` to temporarily disable the Kokkos device for this operation.
.. todo:: Fix reference above.
.. load-example:: RestrictCopyDevice
:file: GuideExampleRuntimeDeviceTracker.cxx
:caption: Disabling a device with :class:`vtkm::cont::RuntimeDeviceTracker`.

@ -6,3 +6,14 @@ Using |VTKm|
:maxdepth: 2
base-types.rst
version.rst
initialization.rst
dataset.rst
io.rst
running-filters.rst
provided-filters.rst
rendering.rst
error-handling.rst
managing-devices.rst
timer.rst
implicit-functions.rst

File diff suppressed because it is too large Load Diff

@ -27,11 +27,8 @@ The ``Initialize`` function is defined in the :file:`vtkm/cont/Initialize.h` hea
:file: VTKmQuickStart.cxx
:caption: Initializing |VTKm|.
.. todo:: Uncomment and add cross reference.
..
``Initialize`` has many options to customize command line argument processing.
See Chapter \ref{chap:Initialization} for more details.
``Initialize`` has many options to customize command line argument processing.
See :chapref:`initialization:Initialization` for more details.
.. didyouknow::
Don't have access to ``argc`` and ``argv``?
@ -52,7 +49,7 @@ These files have a :file:`.vtk` extension.
VTK legacy files can be read using the :class:`vtkm::io::VTKDataSetReader` object, which is declared in the :file:`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 :member:`vtkm::io::VTKDataSetReader::ReadDataSet` method.
The data is then read in by calling the :func:`vtkm::io::VTKDataSetReader::ReadDataSet` method.
.. load-example:: VTKmQuickStartReadFile
:file: VTKmQuickStart.cxx
@ -133,9 +130,9 @@ In our case we only have one ``DataSet`` to render, so we simply create a single
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 :exlineref:`VTKmQuickStartRender:view`.
The image generation is then performed by calling :member:`vtkm::rendering::View::Paint` on the view object (:exlineref:`VTKmQuickStartRender:paint`).
The image generation is then performed by calling :func:`vtkm::rendering::View::Paint` on the view object (:exlineref:`VTKmQuickStartRender:paint`).
However, the rendering done by |VTKm|'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 :member:`vtkm::rendering::View::SaveAs` method (:exlineref:`VTKmQuickStartRender:save`).
The easiest way to see the image is to save it to an image file using the :func:`vtkm::rendering::View::SaveAs` method (:exlineref:`VTKmQuickStartRender:save`).
------------------------------

@ -0,0 +1,661 @@
==============================
Rendering
==============================
.. index:: rendering
Rendering, the generation of images from data, is a key component to visualization.
To assist with rendering, |VTKm| provides a rendering package to produce imagery from data, which is located in the ``vtkm::rendering`` namespace.
The rendering package in |VTKm| is not intended to be a fully featured
rendering system or library. Rather, it is a lightweight rendering package
with two primary use cases:
* New users getting started with |VTKm| need a "quick and dirty" render method to see their visualization results.
* In situ visualization that integrates |VTKm| with a simulation or other data-generation system might need a lightweight rendering method.
Both of these use cases require just a basic rendering platform.
Because |VTKm| is designed to be integrated into larger systems, it does not aspire to have a fully featured rendering system.
.. didyouknow::
|VTKm|'s big sister toolkit VTK is already integrated with |VTKm| and has its own fully featured rendering system.
If you need more rendering capabilities than what |VTKm| provides, you can leverage VTK instead.
------------------------------
Scenes and Actors
------------------------------
.. index::
double: rendering; actor
The primary intent of the rendering package in |VTKm| is to visually display the data that is loaded and processed.
Data are represented in |VTKm| by :class:`vtkm::cont::DataSet` objects, which are described in :chapref:`dataset:Data Sets`.
They are also the object created from :chapref:`io:File I/O` and :chapref:`running-filters:Running Filters`.
To render a :class:`vtkm::cont::DataSet`, the data are wrapped in a
:class:`vtkm::rendering::Actor` class. The :class:`vtkm::rendering::Actor` holds the
components of the :class:`vtkm::cont::DataSet` to render (a cell set, a
coordinate system, and a field). A color table can also be optionally be
specified, but a default color table will be specified otherwise.
.. load-example:: ActorScene
:file: GuideExampleRendering.cxx
:caption: Creating an :class:`vtkm::rendering::Actor` and adding it to a :class:`vtkm::rendering::Scene`.
.. doxygenclass:: vtkm::rendering::Actor
:members:
.. index::
double: rendering; scene
:class:`vtkm::rendering::Actor` objects are collected together in an object called :class:`vtkm::rendering::Scene`.
An :class:`vtkm::rendering::Actor` is added to a :class:`vtkm::rendering::Scene` with the :func:`vtkm::rendering::Scene::AddActor` method.
.. doxygenclass:: vtkm::rendering::Scene
:members:
The following example demonstrates creating a :class:`vtkm::rendering::Scene` with one :class:`vtkm::rendering::Actor`.
------------------------------
Canvas
------------------------------
.. index::
double: rendering; canvas
A canvas is a unit that represents the image space that is the target of the rendering.
The canvas' primary function is to manage the buffers that hold the working image data during the rendering.
The canvas also manages the context and state of the rendering subsystem.
.. index::
double: canvas; ray tracer
:class:`vtkm::rendering::Canvas` is the base class of all canvas objects.
Each type of rendering system has its own canvas subclass, but currently the only rendering system provided by |VTKm| is the internal ray tracer.
The canvas for the ray tracer is :class:`vtkm::rendering::CanvasRayTracer`.
:class:`vtkm::rendering::CanvasRayTracer` is typically constructed by giving the width and height of the image to render.
.. load-example:: Canvas
:file: GuideExampleRendering.cxx
:caption: Creating a canvas for rendering.
.. doxygenclass:: vtkm::rendering::CanvasRayTracer
:members:
.. doxygenclass:: vtkm::rendering::Canvas
:members:
------------------------------
Mappers
------------------------------
.. index::
double: rendering; mapper
A mapper is a unit that converts data (managed by an :class:`vtkm::rendering::Actor`) and issues commands to the rendering subsystem to generate images.
All mappers in |VTKm| are a subclass of :class:`vtkm::rendering::Mapper`.
Different mappers could render different types of data in different ways.
For example, one mapper might render polygonal surfaces whereas another might render polyhedra as a translucent volume.
.. doxygenclass:: vtkm::rendering::Mapper
:members:
..
Also, different rendering systems (as established by the :class:`vtkm::rendering::Canvas`) often require different mappers.
Thus, a mapper should be picked to match both the rendering system of the :class:`vtkm::rendering::Canvas` and the data in the :class:`vtkm::rendering::Actor`.
The following mappers are provided by |VTKm|.
.. doxygenclass:: vtkm::rendering::MapperCylinder
:members:
.. doxygenclass:: vtkm::rendering::MapperGlyphBase
:members:
.. doxygenclass:: vtkm::rendering::MapperGlyphScalar
:members:
.. doxygenclass:: vtkm::rendering::MapperGlyphVector
:members:
.. doxygenclass:: vtkm::rendering::MapperPoint
:members:
.. doxygenclass:: vtkm::rendering::MapperQuad
:members:
.. doxygenclass:: vtkm::rendering::MapperRayTracer
:members:
.. doxygenclass:: vtkm::rendering::MapperVolume
:members:
.. doxygenclass:: vtkm::rendering::MapperWireframer
:members:
------------------------------
Views
------------------------------
.. index::
double: rendering; view
A view is a unit that collects all the structures needed to perform rendering.
It contains everything needed to take a :class:`vtkm::rendering::Scene` and use a :class:`vtkm::rendering::Mapper` to render it onto a :class:`vtkm::rendering::Canvas`.
The view also annotates the image with spatial and scalar properties.
The base class for all views is :class:`vtkm::rendering::View`, which is an abstract class.
You must choose one of the three provided subclasses, :class:`vtkm::rendering::View3D`, :class:`vtkm::rendering::View2D`, and :class:`vtkm::rendering::View3D`, depending on the type of data being presented.
All three view classes take a :class:`vtkm::rendering::Scene`, a :class:`vtkm::rendering::Mapper`, and a :class:`vtkm::rendering::Canvas` as arguments to their constructor.
.. load-example:: ConstructView
:file: GuideExampleRendering.cxx
:caption: Constructing a :class:`vtkm::rendering::View`.
.. doxygenclass:: vtkm::rendering::View
:members:
.. doxygenclass:: vtkm::rendering::View1D
:members:
.. doxygenclass:: vtkm::rendering::View2D
:members:
.. doxygenclass:: vtkm::rendering::View3D
:members:
.. index::
double: color; background
double: color; foreground
The :class:`vtkm::rendering::View` also maintains a background color (the color used in areas where nothing is drawn) and a foreground color (the color used for annotation elements).
By default, the :class:`vtkm::rendering::View` has a black background and a white foreground.
These can be set in the view's constructor, but it is a bit more readable to set them using the :func:`vtkm::rendering::View::SetBackground` and :func:`vtkm::rendering::View::SetForeground` methods.
In either case, the colors are specified using the :class:`vtkm::rendering::Color` helper class, which manages the red, green, and blue color channels as well as an optional alpha channel.
These channel values are given as floating point values between 0 and 1.
.. load-example:: ViewColors
:file: GuideExampleRendering.cxx
:caption: Changing the background and foreground colors of a :class:`vtkm::rendering::View`.
.. commonerrors::
Although the background and foreground colors are set independently, it will be difficult or impossible to see the annotation if there is not enough contrast between the background and foreground colors.
Thus, when changing a :class:`vtkm::rendering::View`'s background color, it is always good practice to also change the foreground color.
.. doxygenclass:: vtkm::rendering::Color
:members:
Once the :class:`vtkm::rendering::View` is constructed, intialized, and set up, it is ready to render.
This is done by calling the :func:`vtkm::rendering::View::Paint` method.
.. load-example:: PaintView
:file: GuideExampleRendering.cxx
:caption: Using :func:`vtkm::rendering::Canvas::Paint` in a display callback.
Putting together :numref:`ex:ConstructView`, :numref:`ex:ViewColors`, and :numref:`ex:PaintView`, the final render of a view looks like that in :numref:`fig:ExampleRendering`.
.. figure:: images/BasicRendering.png
:width: 100%
:name: fig:ExampleRendering
Example output of |VTKm|'s rendering system.
.. Note: BasicRendering.png is generated by the GuideExampleRendering.cxx code.
Of course, the :class:`vtkm::rendering::CanvasRayTracer` created in :numref:`ex:ConstructView` is an offscreen rendering buffer, so you cannot immediately see the image.
When doing batch visualization, an easy way to output the image to a file for later viewing is with the :func:`vtkm::rendering::View::SaveAs` method.
This method can save the image in either PNG or in the portable pixelmap (PPM) format.
.. load-example:: SaveView
:file: GuideExampleRendering.cxx
:caption: Saving the result of a render as an image file.
We visit doing interactive rendering in a GUI later in :secref:`rendering:Interactive Rendering`.
------------------------------
Changing Rendering Modes
------------------------------
:numref:`ex:ConstructView` constructs the default mapper for ray tracing, which renders the data as an opaque solid.
However, you can change the rendering mode by using one of the other mappers listed in :secref:`rendering:Mappers`.
For example, say you just wanted to see a wireframe representation of your data.
You can achieve this by using :class:`vtkm::rendering::MapperWireframer`.
.. index::
double: rendering; wireframe
.. load-example:: MapperEdge
:file: GuideExampleRendering.cxx
:caption: Creating a mapper for a wireframe representation.
Alternatively, perhaps you wish to render just the points of mesh.
:class:`vtkm::rendering::MapperGlyphScalar` renders the points as glyphs and also optionally can scale the glyphs based on field values.
.. load-example:: MapperGlyphScalar
:file: GuideExampleRendering.cxx
:caption: Creating a mapper for point representation.
These mappers respectively render the images shown in :numref:`fig:AlternateMappers`.
Other mappers, such as those that can render translucent volumes, are also available.
.. figure:: images/AlternateRendering.png
:width: 100%
:name: fig:AlternateMappers
Examples of alternate rendering modes using different mappers.
The top left image is rendered with :class:`vtkm::rendering::MapperWireframer`.
The top right and bottom left images are rendered with :class:`vtkm::rendering::MapperGlyphScalar`.
The bottom right image is rendered with :class:`vtkm::rendering::MapperGlyphVector`.
------------------------------
Manipulating the Camera
------------------------------
.. index::
double: rendering; camera
The :class:`vtkm::rendering::View` uses an object called :class:`vtkm::rendering::Camera` to describe the vantage point from which to draw the geometry.
The camera can be retrieved from the :func:`vtkm::rendering::View::GetCamera` method.
That retrieved camera can be directly manipulated or a new camera can be provided by calling :func:`vtkm::rendering::View::SetCamera`.
In this section we discuss camera setups typical during view set up.
Camera movement during interactive rendering is revisited in :secref:`rendering:Camera Movement`.
.. doxygenclass:: vtkm::rendering::Camera
:members:
A :class:`vtkm::rendering::Camera` operates in one of two major modes: 2D mode or 3D mode.
2D mode is designed for looking at flat geometry (or close to flat geometry) that is parallel to the x-y plane.
3D mode provides the freedom to place the camera anywhere in 3D space.
The different modes can be set with :func:`vtkm::rendering::Camera::SetModeTo2D` and :func:`vtkm::rendering::Camera::SetModeTo3D`, respectively.
The interaction with the camera in these two modes is very different.
Common Camera Controls
==============================
Some camera controls operate relative to the rendered image and are common among the 2D and 3D camera modes.
Pan
------------------------------
.. index::
triple: camera; rendering; pan
A camera pan moves the viewpoint left, right, up, or down.
A camera pan is performed by calling the :func:`vtkm::cont::Camera::Pan` method.
:func:`vtkm::cont::Camera::Pan` takes two arguments: the amount to pan in x and the amount to pan in y.
The pan is given with respect to the projected space. So a pan of :math:`1` in
the x direction moves the camera to focus on the right edge of the image
whereas a pan of :math:`-1` in the x direction moves the camera to focus on the
left edge of the image.
.. load-example:: Pan
:file: GuideExampleRenderingInteractive.cxx
:caption: Panning the camera.
Zoom
------------------------------
.. index::
triple: camera; rendering; zoom
A camera zoom draws the geometry larger or smaller.
A camera zoom is performed by calling the :func:`vtkm::rendering::Camera::Zoom` method.
:func:`vtkm::rendering::Camera::Zoom` takes a single argument specifying the zoom factor.
A positive number draws the geometry larger (zoom in), and larger zoom factor results in larger geometry.
Likewise, a negative number draws the geometry smaller (zoom out).
A zoom factor of 0 has no effect.
.. load-example:: Zoom
:file: GuideExampleRenderingInteractive.cxx
:caption: Zooming the camera.
2D Camera Mode
==============================
.. index::
triple: camera; rendering; 2D
The 2D camera is restricted to looking at some region of the x-y plane.
View Range
------------------------------
.. index::
triple: camera; rendering; view range
The vantage point of a 2D camera can be specified by simply giving the region in the x-y plane to look at.
This region is specified by calling :func:`vtkm::rendering::Camera::SetViewRange2D`.
This method takes the left, right, bottom, and top of the region to view.
Typically these are set to the range of the geometry in world space as shown in :numref:`fig:CameraViewRange2D`.
.. figure:: images/CameraViewRange2D.png
:width: 100%
:name: fig:CameraViewRange2D
The view range bounds to give a :class:`vtkm::rendering::Camera`.
3D Camera Mode
==============================
.. index::
triple: camera; rendering; 3D
double: pinhole; camera
The 3D camera is a free-form camera that can be placed anywhere in 3D space and can look in any direction.
The projection of the 3D camera is based on the pinhole camera pinhole camera model in which all viewing rays intersect a single point.
This single point is the camera's position.
Position and Orientation
------------------------------
.. index::
triple: camera; rendering; position
triple: camera; rendering; look at
triple: camera; rendering; focal point
The position of the camera, which is the point where the observer is viewing the scene, can be set with the :func:`vtkm::rendering::Camera::SetPosition` method.
The direction the camera is facing is specified by giving a position to focus on.
This is called either the "look at" point or the focal point and is specified with the :func:`vtkm::rendering::Camera::SetLookAt` method.
:numref:`fig:CameraPositionOrientation3D` shows the relationship between the position and look at points.
.. figure:: images/CameraPositionOrientation.png
:width: 100%
:name: fig:CameraPositionOrientation3D
The position and orientation parameters for a :class:`vtkm::rendering::Camera`.
.. index::
triple: camera; rendering; view up
triple: camera; rendering; up
In addition to specifying the direction to point the camera, the camera must also know which direction is considered "up."
This is specified with the view up vector using the :func:`vtkm::rendering::Camera::SetViewUp` method.
The view up vector points from the camera position (in the center of the image) to the top of the image.
The view up vector in relation to the camera position and orientation is shown in :numref:`fig:CameraPositionOrientation3D`.
.. index::
triple: camera; rendering; field of view
Another important parameter for the camera is its field of view.
The field of view specifies how wide of a region the camera can see.
It is specified by giving the angle in degrees of the cone of visible region emanating from the pinhole of the camera to the :func:`vtkm::rendering::Camera::SetFieldOfView` method.
The field of view angle in relation to the camera orientation is shown in :numref:`fig:CameraPositionOrientation3D`.
A field of view angle of :math:`60^{\circ}` usually works well.
.. index::
triple: camera; rendering; clipping range
triple: camera; rendering; near clip plane
triple: camera; rendering; far clip plane
Finally, the camera must specify a clipping region that defines the valid range of depths for the object.
This is a pair of planes parallel to the image that all visible data must lie in.
Each of these planes is defined simply by their distance to the camera position.
The near clip plane is closer to the camera and must be in front of all geometry.
The far clip plane is further from the camera and must be behind all geometry.
The distance to both the near and far planes are specified with the :func:`vtkm::rendering::Camera::SetClippingRange` method.
:numref:`fig:CameraPositionOrientation3D` shows the clipping planes in relationship to the camera position and orientation.
.. load-example:: CameraPositionOrientation
:file: GuideExampleRenderingInteractive.cxx
:caption: Directly setting :class:`vtkm::rendering::Camera` position and orientation.
Movement
------------------------------
In addition to specifically setting the position and orientation of the camera, :class:`vtkm::rendering::Camera` contains several convenience methods that move the camera relative to its position and look at point.
.. index::
triple: camera; rendering; elevation
triple: camera; rendering; azimuth
Two such methods are elevation and azimuth, which move the camera around the sphere centered at the look at point.
:func:`vtkm::rendering::Camera::Elevation` raises or lowers the camera.
Positive values raise the camera up (in the direction of the view up vector) whereas negative values lower the camera down.
:func:`vtkm::rendering::Camera::Azimuth` moves the camera around the look at point to the left or right.
Positive values move the camera to the right whereas negative values move the camera to the left.
Both :func:`vtkm::rendering::Camera::Elevation` and :func:`vtkm::rendering::Camera::Azimuth` specify the amount of rotation in terms of degrees.
:numref:`fig:CameraMovement` shows the relative movements of :func:`vtkm::rendering::Camera::Elevation` and :func:`vtkm::rendering::Camera::Azimuth`.
.. figure:: images/CameraMovement.png
:width: 100%
:name: fig:CameraMovement
:class:`vtkm::rendering::Camera` movement functions relative to position and orientation.
.. load-example:: CameraMovement
:file: GuideExampleRenderingInteractive.cxx
:caption: Moving the camera around the look at point.
.. commonerrors::
The :func:`vtkm::rendering::Camera::Elevation` and :func:`vtkm::rendering::Camera::Azimuth` methods change the position of the camera, but not the view up vector.
This can cause some wild camera orientation changes when the direction of the camera view is near parallel to the view up vector, which often happens when the elevation is raised or lowered by about 90 degrees.
In addition to rotating the camera around the look at point, you can move the camera closer or further from the look at point.
This is done with the :func:`vtkm::rendering::Camera::Dolly` method.
The :func:`vtkm::rendering::Camera::Dolly` method takes a single value that is the factor to scale the distance between camera and look at point.
Values greater than one move the camera away, values less than one move the camera closer.
The direction of dolly movement is shown in :numref:`fig:CameraMovement`.
Finally, the :func:`vtkm::rendering::Camera::Roll` method rotates the camera around the viewing direction.
It has the effect of rotating the rendered image.
The :func:`vtkm::rendering::Camera::Roll` method takes a single value that is the angle to rotate in degrees.
The direction of roll movement is shown in :numref:`fig:CameraMovement`.
Reset
------------------------------
.. index::
triple: camera; rendering; reset
Setting a specific camera position and orientation can be frustrating, particularly when the size, shape, and location of the geometry is not known a priori.
Typically this involves querying the data and finding a good camera orientation.
To make this process simpler, the :func:`vtkm::rendering::Camera::ResetToBounds` convenience method automatically positions the camera based on the spatial bounds of the geometry.
The most expedient method to find the spatial bounds of the geometry being rendered is to get the :class:`vtkm::rendering::Scene` object and call :func:`vtkm::rendering::Scene::GetSpatialBounds`.
The :class:`vtkm::rendering::Scene` object can be retrieved from the :class:`vtkm::rendering::View`, which, as described in :secref:`rendering:Views`, is the central object for managing rendering.
.. load-example:: ResetCamera
:file: GuideExampleRenderingInteractive.cxx
:caption: Resetting a :class:`vtkm::rendering::Camera` to view geometry.
The :func:`vtkm::rendering::Camera::ResetToBounds` method operates by placing the look at point in the center of the bounds and then placing the position of the camera relative to that look at point.
The position is such that the view direction is the same as before the call to :func:`vtkm::rendering::Camera::ResetToBounds` and the distance between the camera position and look at point has the bounds roughly fill the rendered image.
This behavior is a convenient way to update the camera to make the geometry most visible while still preserving the viewing position.
If you want to reset the camera to a new viewing angle, it is best to set the camera to be pointing in the right direction and then calling :func:`vtkm::rendering::Camera::ResetToBounds` to adjust the position.
.. load-example:: AxisAlignedCamera
:file: GuideExampleRenderingInteractive.cxx
:caption: Resetting a :class:`vtkm::rendering::Camera` to be axis aligned.
------------------------------
Interactive Rendering
------------------------------
.. index::
double: rendering; interactive
So far in our description of |VTKm|'s rendering capabilities we have talked about doing rendering of fixed scenes.
However, an important use case of scientific visualization is to provide an interactive rendering system to explore data.
In this case, you want to render into a GUI application that lets the user interact manipulate the view.
The full design of a 3D visualization application is well outside the scope of this book, but we discuss in general terms what you need to plug |VTKm|'s rendering into such a system.
In this section we discuss two important concepts regarding interactive rendering.
First, we need to write images into a GUI while they are being rendered.
Second, we want to translate user interaction to camera movement.
Rendering Into a GUI
==============================
.. index::
triple: interactive; rendering; OpenGL
Before being able to show rendering to a user, we need a system rendering context in which to push the images.
In this section we demonstrate the display of images using the OpenGL rendering system, which is common for scientific visualization applications.
That said, you could also use other rendering systems like DirectX or even paste images into a blank widget.
Creating an OpenGL context varies depending on the OS platform you are using.
If you do not already have an application you want to integrate with |VTKm|'s rendering, you may wish to start with graphics utility API such as GLUT or GLFW.
The process of initializing an OpenGL context is not discussed here.
The process of rendering into an OpenGL context is straightforward.
First call :func:`vtkm::rendering::View::Paint` on the :class:`vtkm::rendering::View` object to do the actual rendering.
Second, get the image color data out of the :class:`vtkm::rendering::View`'s :class:`vtkm::rendering::Canvas` object.
This is done by calling :func:`vtkm::rendering::Canvas::GetColorBuffer`.
This will return a :class:`vtkm::cont::ArrayHandle` object containing the image's pixel color data.
(:class:`vtkm::cont::ArrayHandle` is discussed in detail in Chapter \ref{chap:BasicArrayHandles} and subsequent chapters.)
A raw pointer can be pulled out of this :class:`vtkm::cont::ArrayHandle` by casting it to the :class:`vtkm::cont::ArrayHandleBase` subclass and calling the :func:`vtkm::cont::ArrayHandleBase::GetReadPointer` method on that.
Third, the pixel color data are pasted into the OpenGL render context.
There are multiple ways to do so, but the most straightforward way is to use the ``glDrawPixels`` function provided by OpenGL.
Fourth, swap the OpenGL buffers.
The method to swap OpenGL buffers varies by OS platform.
The aforementioned graphics libraries GLUT and GLFW each provide a function for doing so.
.. todo:: Fix chapter reference above.
.. load-example:: RenderToOpenGL
:file: GuideExampleRenderingInteractive.cxx
:caption: Rendering a :class:`vtkm::rendering::View` and pasting the result to an active OpenGL context.
Camera Movement
==============================
.. index::
triple: interactive; rendering; camera
triple: camera; rendering; mouse
When interactively manipulating the camera in a windowing system, the camera is usually moved in response to mouse movements.
Typically, mouse movements are detected through callbacks from the windowing system back to your application.
Once again, the details on how this works depend on your windowing system.
The assumption made in this section is that through the windowing system you will be able to track the x-y pixel location of the mouse cursor at the beginning of the movement and the end of the movement.
Using these two pixel coordinates, as well as the current width and height of the render space, we can make several typical camera movements.
.. commonerrors::
Pixel coordinates in |VTKm|'s rendering system originate in the lower-left corner of the image.
However, windowing systems generally report mouse coordinates with the origin in the *upper*-left corner.
The upshot is that the y coordinates will have to be reversed when translating mouse coordinates to |VTKm| image coordinates.
This inverting is present in all the following examples.
Interactive Rotate
------------------------------
.. index::
double: mouse; rotation
double: rotation; rendering
A common and important mode of interaction with 3D views is to allow the user to rotate the object under inspection by dragging the mouse.
To facilitate this type of interactive rotation, :class:`vtkm::rendering::Camera` provides a convenience method named :func:`vtkm::rendering::Camera::TrackballRotate`.
It takes a start and end position of the mouse on the image and rotates viewpoint as if the user grabbed a point on a sphere centered in the image at the start position and moved under the end position.
The :func:`vtkm::rendering::Camera::TrackballRotate` method is typically called from within a mouse movement callback.
The callback must record the pixel position from the last event and the new pixel position of the mouse.
Those pixel positions must be normalized to the range -1 to 1 where the position (-1,-1) refers to the lower left of the image and (1,1) refers to the upper right of the image.
The following example demonstrates the typical operations used to establish rotations when dragging the mouse.
.. load-example:: MouseRotate
:file: GuideExampleRenderingInteractive.cxx
:caption: Interactive rotations through mouse dragging with :func:`vtkm::rendering::Camera::TrackballRotate`.
Interactive Pan
------------------------------
.. index::
double: mouse; pan
double: pan; rendering
Panning can be performed by calling :func:`vtkm::rendering::Camera::Pan` with the translation relative to the width and height of the canvas.
For the translation to track the movement of the mouse cursor, simply scale the pixels the mouse has traveled by the width and height of the image.
.. load-example:: MousePan
:file: GuideExampleRenderingInteractive.cxx
:caption: Pan the view based on mouse movements.
Interactive Zoom
------------------------------
.. index::
double: mouse; zoom
double: zoom; rendering
Zooming can be performed by calling :func:`vtkm::rendering::Camera::Zoom` with a positive or negative zoom factor.
When using :func:`vtkm::rendering::Camera::Zoom` to respond to mouse movements, a natural zoom will divide the distance traveled by the mouse pointer by the width or height of the screen as demonstrated in the following example.
.. load-example:: MouseZoom
:file: GuideExampleRenderingInteractive.cxx
:caption: Zoom the view based on mouse movements.
------------------------------
Color Tables
------------------------------
.. index::
double: rendering; color tables
An important feature of |VTKm|'s rendering units is the ability to :index:`pseudocolor` objects based on scalar data.
This technique maps each scalar to a potentially unique color.
This mapping from scalars to colors is defined by a :class:`vtkm::cont::ColorTable` object.
A :class:`vtkm::cont::ColorTable` can be specified as an optional argument when constructing a :class:`vtkm::rendering::Actor`.
(Use of :class:`vtkm::rendering::Actor` is discussed in :secref:`rendering:Scenes and Actors`.)
.. load-example:: SpecifyColorTable
:file: GuideExampleRenderingInteractive.cxx
:caption: Specifying a :class:`vtkm::cont::ColorTable` for a :class:`vtkm::rendering::Actor`.
.. doxygenclass:: vtkm::cont::ColorTable
:members:
The easiest way to create a :class:`vtkm::cont::ColorTable` is to provide the
name of one of the many predefined sets of color provided by VTK-m. A list
of all available predefined color tables is provided below.
.. This file and all the images in images/color-tables are built by the GuideExampleColorTables test.
.. include:: color-table-presets.rst
* |Viridis| ``Viridis``
Matplotlib Virdis, which is designed to have perceptual uniformity, accessibility to color blind viewers, and good conversion to black and white.
This is the default color map.
* |Cool-to-Warm| ``Cool to Warm``
A color table designed to be perceptually even, to work well on shaded 3D surfaces, and to generally perform well across many uses.
* |Cool-to-Warm-Extended| ``Cool to Warm Extended``
This colormap is an expansion on cool to warm that moves through a wider range of hue and saturation.
Useful if you are looking for a greater level of detail, but the darker colors at the end might interfere with 3D surfaces.
* |Inferno| ``Inferno``
Matplotlib Inferno, which is designed to have perceptual uniformity, accessibility to color blind viewers, and good conversion to black and white.
* |Plasma| ``Plasma``
Matplotlib Plasma, which is designed to have perceptual uniformity, accessibility to color blind viewers, and good conversion to black and white.
* |Black-Body-Radiation| ``Black Body Radiation``
The colors are inspired by the wavelengths of light from black body radiation.
The actual colors used are designed to be perceptually uniform.
* |X-Ray| ``X Ray``
Greyscale colormap useful for making volume renderings similar to what you would expect in an x-ray.
* |Green| ``Green``
A sequential color map of green varied by saturation.
* |Black---Blue---White| ``Black - Blue - White``
A sequential color map from black to blue to white.
* |Blue-to-Orange| ``Blue to Orange``
A double-ended (diverging) color table that goes from dark blues to a neutral white and then a dark orange at the other end.
* |Gray-to-Red| ``Gray to Red``
A double-ended (diverging) color table with black/gray at the low end and orange/red at the high end.
* |Cold-and-Hot| ``Cold and Hot``
A double-ended color map with a black middle color and diverging values to either side.
Colors go from red to yellow on the positive side and through blue on the negative side.
* |Blue---Green---Orange| ``Blue - Green - Orange``
A three-part color map with blue at the low end, green in the middle, and orange at the high end.
* |Yellow---Gray---Blue| ``Yellow - Gray - Blue``
A three-part color map with yellow at the low end, gray in the middle, and blue at the high end.
* |Rainbow-Uniform| ``Rainbow Uniform``
A color table that spans the hues of a rainbow.
This color table modifies the hues to make them more perceptually uniform than the raw color wavelengths.
* |Jet| ``Jet``
A rainbow color table that adds some darkness for greater perceptual resolution.
* |Rainbow-Desaturated| ``Rainbow Desaturated``
Basic rainbow colors with periodic dark points to increase the local discriminability.

@ -0,0 +1,188 @@
==============================
Running Filters
==============================
.. index:: filter
Filters are functional units that take data as input and write new data as output.
Filters operate on :class:`vtkm::cont::DataSet` objects, which are described in :chapref:`dataset:Data Sets`.
.. didyouknow::
The structure of filters in |VTKm| is significantly simpler than their counterparts in VTK.
VTK filters are arranged in a dataflow network (a.k.a. a visualization pipeline) and execution management is handled automatically.
In contrast, |VTKm| filters are simple imperative units, which are simply called with input data and return output data.
|VTKm| comes with several filters ready for use.
This chapter gives an overview of how to run the filters.
:chapref:`provided-filters:Provided Filters` describes the common filters provided by |VTKm|.
Later, :partref:`part-developing:Developing Algorithms` describes the necessary steps in creating new filters in |VTKm|.
------------------------------
Basic Filter Operation
------------------------------
Different filters will be used in different ways, but the basic operation of all filters is to instantiate the filter class, set the state parameters on the filter object, and then call the filter's :func:`vtkm::filter::Filter::Execute` method.
It takes a :class:`vtkm::cont::DataSet` and returns a new :class:`vtkm::cont::DataSet`, which contains the modified data.
The :func:`vtkm::filter::Filter::Execute` method can alternately take a :class:`vtkm::cont::PartitionedDataSet` object, which is a composite of :class:`vtkm::cont::DataSet` objects.
In this case :func:`vtkm::filter::Filter::Execute` will return another :class:`vtkm::cont::PartitionedDataSet` object.
The following example provides a simple demonstration of using a filter.
It specifically uses the point elevation filter to estimate the air pressure at each point based on its elevation.
.. load-example:: PointElevation
:file: GuideExampleProvidedFilters.cxx
:caption: Using :class:`vtkm::filter::field_transform::PointElevation` to estiate air pressure.
We see that this example follows the previously described procedure of constructing the filter (:exlineref:`line %s<PointElevation:Construct>`), setting the state parameters (:exlineref:`lines %s<PointElevation:SetStateStart>` :exlineref:`-- %s<PointElevation:SetStateEnd>`), and finally executing the filter on a :class:`vtkm::cont::DataSet` (:exlineref:`line %s<PointElevation:Execute>`).
.. index:: field
Every :class:`vtkm::cont::DataSet` object contains a list of *fields*, which describe some numerical value associated with different parts of the data set in space.
Fields often represent physical properties such as temperature, pressure, or velocity.
Fields are identified with string names.
There are also special fields called coordinate systems that describe the location of points in space.
Field are mentioned here because they are often used as input data to the filter's operation and filters often generate new fields in the output.
This is the case in :numref:`ex:PointElevation`.
In :exlineref:`line %s<PointElevation:SetInputField>` the coordinate system is set as the input field and in :exlineref:`line %s<PointElevation:SetOutputField>` the name to use for the generated output field is selected.
------------------------------
Advanced Field Management
------------------------------
.. index::
double: filter; fields
Most filters work with fields as inputs and outputs to their algorithms.
Although in the previous discussions of the filters we have seen examples of specifying fields, these examples have been kept brief in the interest of clarity.
In this section we revisit how filters manage fields and provide more detailed documentation of the controls.
Note that not all of the discussion in this section applies to all the filters provided by |VTKm|.
For example, not all filters have a specified input field.
But where possible, the interface to the filter objects is kept consistent.
Input Fields
==============================
.. index::
triple: filter; input; fields
Filters that take one or more fields as input have a common set of methods to set the "active" fields to operate on.
They might also have custom methods to ease setting the appropriate fields, but these are the base methods.
.. doxygenfunction:: vtkm::filter::FilterField::SetActiveField(const std::string&, vtkm::cont::Field::Association)
.. doxygenfunction:: vtkm::filter::FilterField::SetActiveField(vtkm::IdComponent, const std::string&, vtkm::cont::Field::Association)
.. doxygenfunction:: vtkm::filter::FilterField::GetActiveFieldName
.. doxygenfunction:: vtkm::filter::FilterField::GetActiveFieldAssociation
.. doxygenfunction:: vtkm::filter::FilterField::SetActiveCoordinateSystem(vtkm::Id)
.. doxygenfunction:: vtkm::filter::FilterField::SetActiveCoordinateSystem(vtkm::IdComponent, vtkm::Id)
.. doxygenfunction:: vtkm::filter::FilterField::GetActiveCoordinateSystemIndex
.. doxygenfunction:: vtkm::filter::FilterField::SetUseCoordinateSystemAsField(bool)
.. doxygenfunction:: vtkm::filter::FilterField::SetUseCoordinateSystemAsField(vtkm::IdComponent, bool)
.. doxygenfunction:: vtkm::filter::FilterField::GetUseCoordinateSystemAsField
.. doxygenfunction:: vtkm::filter::FilterField::GetNumberOfActiveFields
The :func:`vtkm::filter::FilterField::SetActiveField` takes an optional argument that specifies which topological elements the field is associated with (such as points or cells).
The :enum:`vtkm::cont::Field::Association` enumeration is used to select the field association.
.. load-example:: SetActiveFieldWithAssociation
:file: GuideExampleProvidedFilters.cxx
:caption: Setting a field's active filter with an association.
.. commonerrors::
It is possible to have two fields with the same name that are only differentiable by the association.
That is, you could have a point field and a cell field with different data but the same name.
Thus, it is best practice to specify the field association when possible.
Likewise, it is poor practice to have two fields with the same name, particularly if the data are not equivalent in some way.
It is often the case that fields are selected without an association.
It is also possible to set the active scalar field as a coordinate system of the data.
A coordinate system essentially provides the spatial location of the points of the data and they have a special place in the :class:`vtkm::cont::DataSet` structure.
(See :secref:`dataset:Coordinate Systems` for details on coordinate systems.)
You can use a coordinate system as the active scalars by calling the :func:`vtkm::filter::FilterField::SetUseCoordinateSystemAsField` method with a true flag.
Since a :class:`vtkm::cont::DataSet` can have multiple coordinate systems, you can select the desired coordinate system with :func:`vtkm::filter::FilterField::SetActiveCoordinateSystem`.
(By default, the first coordinate system, index 0, will be used.)
.. load-example:: SetCoordinateSystem
:file: GuideExampleProvidedFilters.cxx
:caption: Setting the active coordinate system.
Passing Fields from Input to Output
========================================
.. index::
triple: filter; passing; fields
After a filter successfully executes and returns a new data set, fields are mapped from input to output.
Depending on what operation the filter does, this could be a simple shallow copy of an array, or it could be a computed operation.
By default, the filter will automatically pass all fields from input to output (performing whatever transformations are necessary).
You can control which fields are passed (and equivalently which are not) with the :func:`vtkm::filter::Filter::SetFieldsToPass` methods.
.. doxygenfunction:: vtkm::filter::Filter::SetFieldsToPass(vtkm::filter::FieldSelection&&)
There are multiple ways to to use :func:`vtkm::filter::Filter::SetFieldsToPass` to control what fields are passed.
If you want to turn off all fields so that none are passed, call :func:`vtkm::filter::Filter::SetFieldsToPass` with :enum:`vtkm::filter::FieldSelection::Mode::None`.
.. load-example:: PassNoFields
:file: GuideExampleProvidedFilters.cxx
:caption: Turning off the passing of all fields when executing a filter.
If you want to pass one specific field, you can pass that field's name to :func:`vtkm::filter::Filter::SetFieldsToPass`.
.. load-example:: PassOneField
:file: GuideExampleProvidedFilters.cxx
:caption: Setting one field to pass by name.
Or you can provide a list of fields to pass by giving :func:`vtkm::filter::Filter::SetFieldsToPass` an initializer list of names.
.. load-example:: PassListOfFields
:file: GuideExampleProvidedFilters.cxx
:caption: Using a list of fields for a filter to pass.
If you want to instead select a list of fields to *not* pass, you can add :enum:`vtkm::filter::FieldSelection::Mode::Exclude` as an argument to :func:`vtkm::filter::Filter::SetFieldsToPass`.
.. load-example:: PassExcludeFields
:file: GuideExampleProvidedFilters.cxx
:caption: Excluding a list of fields for a filter to pass.
Ultimately, :func:`vtkm::filter::Filter::SetFieldsToPass` takes a :class:`vtkm::filter::FieldSelection` object.
You can create one directly to select (or exclude) specific fields and their associations.
.. load-example:: FieldSelection
:file: GuideExampleProvidedFilters.cxx
:caption: Using :class:`vtkm::filter::FieldSelection` to select cells to pass.
It is also possible to specify field attributions directly to :func:`vtkm::filter::Filter::SetFieldsToPass`.
If you only have one field, you can just specify both the name and attribution.
If you have multiple fields, you can provide an initializer list of ``std::pair`` or :class:`vtkm::Pair` containing a ``std::string`` and a :enum:`vtkm::cont::Field::Association`.
In either case, you can add an optional last argument of :enum:`vtkm::filter::FieldSelection::Mode::Exclude` to exclude the specified filters instead of selecting them.
.. load-example:: PassFieldAndAssociation
:file: GuideExampleProvidedFilters.cxx
:caption: Selecting one field and its association for a filter to pass.
.. load-example:: PassListOfFieldsAndAssociations
:file: GuideExampleProvidedFilters.cxx
:caption: Selecting a list of fields and their associations for a filter to pass.
Note that coordinate systems in a :class:`vtkm::cont::DataSet` are simply links to point fields, and by default filters will pass coordinate systems regardless of the field selection flags.
To prevent a filter from passing a coordinate system if its associated field is not selected, use the :func:`vtkm::filter::Filter::SetPassCoordinateSystems` method.
.. doxygenfunction:: vtkm::filter::Filter::SetPassCoordinateSystems
.. doxygenfunction:: vtkm::filter::Filter::GetPassCoordinateSystems
.. load-example:: PassNoCoordinates
:file: GuideExampleProvidedFilters.cxx
:caption: Turning off the automatic selection of fields associated with a :class:`vtkm::cont::DataSet`'s coordinate system.

@ -0,0 +1,42 @@
==============================
Timers
==============================
.. index:: timer
It is often the case that you need to measure the time it takes for an operation to happen.
This could be for performing measurements for algorithm study or it could be to dynamically adjust scheduling.
Performing timing in a multi-threaded environment can be tricky because operations happen asynchronously.
To ensure that accurate timings can be made, |VTKm| provides a :class:`vtkm::cont::Timer` class to provide an accurate measurement of operations that happen on devices that |VTKm| can use.
By default, :class:`vtkm::cont::Timer` will time operations on all possible devices.
The timer is started by calling the :func:`vtkm::cont::Timer::Start` method.
The timer can subsequently be stopped by calling :func:`vtkm::cont::Timer::Stop`.
The time elapsed between calls to :func:`vtkm::cont::Timer::Start` and :func:`vtkm::cont::Timer::Stop` (or the current time if :func:`vtkm::cont::Timer::Stop` was not called) can be retrieved with a call to the :func:`vtkm::cont::Timer::GetElapsedTime` method.
Subsequently calling :func:`vtkm::cont::Timer::Start` again will restart the timer.
.. load-example:: Timer
:file: GuideExampleTimer.cxx
:caption: Using :class:`vtkm::cont::Timer`.
.. commonerrors::
Some device require data to be copied between the host CPU and the device.
In this case you might want to measure the time to copy data back to the host.
This can be done by "touching" the data on the host by getting a control portal.
The |VTKm| :class:`vtkm::cont::Timer` does its best to capture the time it takes for all parallel operations run between calls to :func:`vtkm::cont::Timer::Start` and :func:`vtkm::cont::Timer::Stop` to complete.
It does so by synchronizing to concurrent execution on devices that might be in use.
.. commonerrors::
Because :class:`vtkm::cont::Timer` synchronizes with devices (essentially waiting for the device to finish executing), that can have an effect on how your program runs.
Be aware that using a :class:`vtkm::cont::Timer` can itself change the performance of your code.
In particular, starting and stopping the timer many times to measure the parts of a sequence of operations can potentially make the whole operation run slower.
By default, :class:`vtkm::cont::Timer` will synchronize with all active devices.
However, if you want to measure the time for a specific device, then you can pass the device adapter tag or id to :class:`vtkm::cont::Timer`'s constructor.
You can also change the device being used by passing a device adapter tag or id to the :func:`vtkm::cont::Timer::Reset` method.
A device can also be specified through an optional argument to the :func:`vtkm::cont::Timer::GetElapsedTime` method.
.. doxygenclass:: vtkm::cont::Timer
:members:

@ -0,0 +1,67 @@
==============================
VTK-m Version
==============================
.. index:: version
As the |VTKm| code evolves, changes to the interface and behavior will
inevitably happen.
Consequently, code that links into |VTKm| might need a specific version of
|VTKm| or changes its behavior based on what version of |VTKm| it is using.
To facilitate this, |VTKm| software is managed with a versioning system and
advertises its version in multiple ways.
As with many software products, |VTKm| has three version numbers: major,
minor, and patch.
The major version represents significant changes in the |VTKm|
implementation and interface.
Changes in the major version include backward incompatible changes.
The minor version represents added functionality.
Generally, changes in the minor version to not introduce changes to the API.
The patch version represents fixes provided after a release occurs.
Patch versions represent minimal change and do not add features.
.. index::
triple: CMake ; VTK-m package ; version
If you are writing a software package that is managed by CMake and load |VTKm| with the :cmake:command:`find_package` command as described in :secref:`building:Linking to |VTKm|`, then you can query the |VTKm| version directly in the CMake configuration.
When you load |VTKm| with :cmake:command:`find_package`, CMake sets the variables :cmake:variable:`VTKm_VERSION_MAJOR`, :cmake:variable:`VTKm_VERSION_MINOR`, and :cmake:variable:`VTKm_VERSION_PATCH` to the major, minor, and patch versions, respectively.
Additionally, :cmake:variable:`VTKm_VERSION` is set to the "major.minor" version number and :cmake:variable:`VTKm_VERSION_FULL` is set to the "major.minor.patch" version number.
If the current version of |VTKm| is actually a development version that is in between releases of |VTKm|, then and abbreviated SHA of the git commit is also included as part of :cmake:variable:`VTKm_VERSION_FULL`.
.. didyouknow::
If you have a specific version of |VTKm| required for your software, you can also use the version option to the :cmake:command:`find_package` CMake command.
The :cmake:command:`find_package` command takes an optional version argument that causes the command to fail if the wrong version of the package is found.
.. index:: version ; macro
It is also possible to query the |VTKm| version directly in your code through preprocessor macros.
The :file:`vtkm/Version.h` header file defines the following preprocessor macros to identify the |VTKm| version.
.. c:macro:: VTKM_VERSION
The version number of the loaded |VTKm| package.
This is in the form "major.minor".
.. c:macro:: VTKM_VERSION_FULL
The extended version number of the |VTKm| package including patch and in-between-release information.
This is in the form "major.minor.patch[.gitsha1]" where "gitsha" is only included if the source code is in between releases.
.. c:macro:: VTKM_VERSION_MAJOR
The major |VTKm| version number.
.. c:macro:: VTKM_VERSION_MINOR
The minor |VTKm| version number.
.. c:macro:: VTKM_VERSION_PATCH
The patch |VTKm| version number.
.. commonerrors::
Note that the CMake variables all begin with ``VTKm_`` (lowercase "m") whereas the preprocessor macros begin with ``VTKM_`` (all uppercase).
This follows the respective conventions of CMake variables and preprocessor macros.
Note that :file:`vtkm/Version.h` does not include any other |VTKm| header files.
This gives your code a chance to load, query, and react to the |VTKm| version before loading any |VTKm| code proper.

@ -6,5 +6,10 @@ TESTING_DIR
examples
TEST_DEPENDS
vtkm_cont
vtkm_filter_contour
vtkm_filter_field_conversion
vtkm_filter_field_transform
vtkm_filter_flow
vtkm_filter_geometry_refinement
vtkm_filter_mesh_info
vtkm_rendering

@ -42,11 +42,27 @@ public:
using Scalar = vtkm::FloatDefault;
using Vector = vtkm::Vec<Scalar, 3>;
/// @brief Evaluate the value of the implicit function.
///
/// The `Value()` method for an implicit function takes a `vtkm::Vec3f` and
/// returns a `vtkm::FloatDefault` representing the orientation of the point
/// with respect to the implicit function's shape. Negative scalar values
/// represent vector points inside of the implicit function's shape. Positive
/// scalar values represent vector points outside the implicit function's shape.
/// Zero values represent vector points that lie on the surface of the implicit
/// function.
VTKM_EXEC_CONT Scalar Value(Scalar x, Scalar y, Scalar z) const
{
return reinterpret_cast<const Derived*>(this)->Value(Vector(x, y, z));
}
/// @brief Evaluate the gradient of the implicit function.
///
/// The ``Gradient()`` method for an implicit function takes a `vtkm::Vec3f`
/// and returns a `vtkm::Vec3f` representing the pointing direction from the
/// implicit function's shape. Gradient calculations are more object shape
/// specific. It is advised to look at the individual shape implementations
/// for specific implicit functions.
VTKM_EXEC_CONT Vector Gradient(Scalar x, Scalar y, Scalar z) const
{
return reinterpret_cast<const Derived*>(this)->Gradient(Vector(x, y, z));
@ -130,9 +146,9 @@ private:
};
//============================================================================
/// \brief Implicit function for a box
/// @brief Implicit function for a box
///
/// \c Box computes the implicit function and/or gradient for a axis-aligned
/// `Box` computes the implicit function and/or gradient for a axis-aligned
/// bounding box. Each side of the box is orthogonal to all other sides
/// meeting along shared edges and all faces are orthogonal to the x-y-z
/// coordinate axes.
@ -140,41 +156,50 @@ private:
class VTKM_ALWAYS_EXPORT Box : public internal::ImplicitFunctionBase<Box>
{
public:
/// \brief Construct box with center at (0,0,0) and each side of length 1.0.
/// @brief Construct box with center at (0,0,0) and each side of length 1.0.
VTKM_EXEC_CONT Box()
: MinPoint(Vector(Scalar(-0.5)))
, MaxPoint(Vector(Scalar(0.5)))
{
}
/// @brief Construct a box with the specified minimum and maximum point.
VTKM_EXEC_CONT Box(const Vector& minPoint, const Vector& maxPoint)
: MinPoint(minPoint)
, MaxPoint(maxPoint)
{
}
/// @brief Construct a box with the specified minimum and maximum point.
VTKM_EXEC_CONT Box(Scalar xmin, Scalar xmax, Scalar ymin, Scalar ymax, Scalar zmin, Scalar zmax)
: MinPoint(xmin, ymin, zmin)
, MaxPoint(xmax, ymax, zmax)
{
}
/// @brief Construct a box that encompasses the given bounds.
VTKM_CONT Box(const vtkm::Bounds& bounds) { this->SetBounds(bounds); }
/// @brief Specify the minimum coordinate of the box.
VTKM_CONT void SetMinPoint(const Vector& point) { this->MinPoint = point; }
/// @brief Specify the maximum coordinate of the box.
VTKM_CONT void SetMaxPoint(const Vector& point) { this->MaxPoint = point; }
/// @copydoc SetMinPoint
VTKM_EXEC_CONT const Vector& GetMinPoint() const { return this->MinPoint; }
/// @copydoc SetMaxPoint
VTKM_EXEC_CONT const Vector& GetMaxPoint() const { return this->MaxPoint; }
/// @brief Specify the size and location of the box by the bounds it encompasses.
VTKM_CONT void SetBounds(const vtkm::Bounds& bounds)
{
this->SetMinPoint({ Scalar(bounds.X.Min), Scalar(bounds.Y.Min), Scalar(bounds.Z.Min) });
this->SetMaxPoint({ Scalar(bounds.X.Max), Scalar(bounds.Y.Max), Scalar(bounds.Z.Max) });
}
/// @copydoc SetBounds
VTKM_EXEC_CONT vtkm::Bounds GetBounds() const
{
return vtkm::Bounds(vtkm::Range(this->MinPoint[0], this->MaxPoint[0]),
@ -182,6 +207,7 @@ public:
vtkm::Range(this->MinPoint[2], this->MaxPoint[2]));
}
/// @copydoc internal::ImplicitFunctionBase::Value
VTKM_EXEC_CONT Scalar Value(const Vector& point) const
{
Scalar minDistance = vtkm::NegativeInfinity32();
@ -250,6 +276,7 @@ public:
}
}
/// @copydoc internal::ImplicitFunctionBase::Gradient
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const
{
vtkm::IdComponent minAxis = 0;
@ -400,6 +427,8 @@ public:
{
}
/// Construct a cylinder with the given axis and radius.
/// The cylinder is centered at the origin.
VTKM_EXEC_CONT Cylinder(const Vector& axis, Scalar radius)
: Center(Scalar(0))
, Axis(axis)
@ -407,6 +436,7 @@ public:
{
}
/// Construct a cylinder at the given center, axis, and radius.
VTKM_EXEC_CONT Cylinder(const Vector& center, const Vector& axis, Scalar radius)
: Center(center)
, Axis(vtkm::Normal(axis))
@ -414,12 +444,18 @@ public:
{
}
/// @brief Specify the center of the cylinder.
///
/// The axis of the cylinder goes through the center.
VTKM_CONT void SetCenter(const Vector& center) { this->Center = center; }
/// @brief Specify the direction of the axis of the cylinder.
VTKM_CONT void SetAxis(const Vector& axis) { this->Axis = vtkm::Normal(axis); }
/// @brief Specify the radius of the cylinder.
VTKM_CONT void SetRadius(Scalar radius) { this->Radius = radius; }
/// @copydoc internal::ImplicitFunctionBase::Value
VTKM_EXEC_CONT Scalar Value(const Vector& point) const
{
Vector x2c = point - this->Center;
@ -427,6 +463,7 @@ public:
return vtkm::Dot(x2c, x2c) - (proj * proj) - (this->Radius * this->Radius);
}
/// @copydoc internal::ImplicitFunctionBase::Gradient
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const
{
Vector x2c = point - this->Center;
@ -442,20 +479,25 @@ private:
};
//============================================================================
/// \brief Implicit function for a frustum
/// @brief Implicit function for a frustum
class VTKM_ALWAYS_EXPORT Frustum : public vtkm::internal::ImplicitFunctionBase<Frustum>
{
public:
/// \brief Construct axis-aligned frustum with center at (0,0,0) and each side of length 1.0.
/// @brief Construct axis-aligned frustum with center at (0,0,0) and each side of length 1.0.
Frustum() = default;
/// @brief Construct a frustum defined with 6 planes of the given points and normals.
VTKM_EXEC_CONT Frustum(const Vector points[6], const Vector normals[6])
{
this->SetPlanes(points, normals);
}
/// @brief Construct a frustum defined by the 8 points of the bounding hexahedron.
///
/// The points should be specified in the order of hex-cell vertices
VTKM_EXEC_CONT explicit Frustum(const Vector points[8]) { this->CreateFromPoints(points); }
/// @brief Specifies the 6 planes of the frustum.
VTKM_EXEC void SetPlanes(const Vector points[6], const Vector normals[6])
{
for (vtkm::Id index : { 0, 1, 2, 3, 4, 5 })
@ -468,6 +510,7 @@ public:
}
}
/// @brief Set one of the 6 planes of the frustum.
VTKM_EXEC void SetPlane(int idx, const Vector& point, const Vector& normal)
{
VTKM_ASSERT((idx >= 0) && (idx < 6));
@ -475,6 +518,7 @@ public:
this->Normals[idx] = normal;
}
/// @copydoc SetPlanes
VTKM_EXEC_CONT void GetPlanes(Vector points[6], Vector normals[6]) const
{
for (vtkm::Id index : { 0, 1, 2, 3, 4, 5 })
@ -491,7 +535,9 @@ public:
VTKM_EXEC_CONT const Vector* GetNormals() const { return this->Normals; }
// The points should be specified in the order of hex-cell vertices
/// @brief Specifies the frustum as the 8 points of the bounding hexahedron.
///
/// The points should be specified in the order of hex-cell vertices
VTKM_EXEC_CONT void CreateFromPoints(const Vector points[8])
{
// XXX(clang-format-3.9): 3.8 is silly. 3.9 makes it look like this.
@ -512,6 +558,7 @@ public:
}
}
/// @copydoc internal::ImplicitFunctionBase::Value
VTKM_EXEC_CONT Scalar Value(const Vector& point) const
{
Scalar maxVal = vtkm::NegativeInfinity<Scalar>();
@ -525,6 +572,7 @@ public:
return maxVal;
}
/// @copydoc internal::ImplicitFunctionBase::Gradient
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const
{
Scalar maxVal = vtkm::NegativeInfinity<Scalar>();
@ -581,18 +629,31 @@ public:
{
}
/// @brief Specify the origin of the plane.
///
/// The origin can be any point on the plane.
VTKM_CONT void SetOrigin(const Vector& origin) { this->Origin = origin; }
/// @brief Specify the normal vector to the plane.
///
/// The magnitude of the plane does not matter (so long as it is more than zero) in terms
/// of the location of the plane where the implicit function equals 0. However, if offsets
/// away from the plane matter then the magnitude determines the scale of the value away
/// from the plane.
VTKM_CONT void SetNormal(const Vector& normal) { this->Normal = normal; }
/// @copydoc SetOrigin
VTKM_EXEC_CONT const Vector& GetOrigin() const { return this->Origin; }
/// @copydoc SetNormal
VTKM_EXEC_CONT const Vector& GetNormal() const { return this->Normal; }
/// @copydoc internal::ImplicitFunctionBase::Value
VTKM_EXEC_CONT Scalar Value(const Vector& point) const
{
return vtkm::Dot(point - this->Origin, this->Normal);
}
/// @copydoc internal::ImplicitFunctionBase::Gradient
VTKM_EXEC_CONT Vector Gradient(const Vector&) const { return this->Normal; }
private:
@ -625,25 +686,32 @@ public:
{
}
/// Construct a sphere with the given center and radius.
VTKM_EXEC_CONT Sphere(Vector center, Scalar radius)
: Radius(radius)
, Center(center)
{
}
/// Specify the radius of the sphere.
VTKM_CONT void SetRadius(Scalar radius) { this->Radius = radius; }
/// Specify the center of the sphere.
VTKM_CONT void SetCenter(const Vector& center) { this->Center = center; }
/// @copydoc SetRadius
VTKM_EXEC_CONT Scalar GetRadius() const { return this->Radius; }
/// @copydoc SetCenter
VTKM_EXEC_CONT const Vector& GetCenter() const { return this->Center; }
/// @copydoc internal::ImplicitFunctionBase::Value
VTKM_EXEC_CONT Scalar Value(const Vector& point) const
{
return vtkm::MagnitudeSquared(point - this->Center) - (this->Radius * this->Radius);
}
/// @copydoc internal::ImplicitFunctionBase::Gradient
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const
{
return Scalar(2) * (point - this->Center);
@ -689,6 +757,8 @@ public:
return this->Planes[idx];
}
VTKM_CONT vtkm::VecVariable<vtkm::Plane, MaxNumPlanes> GetPlanes() const { return this->Planes; }
/// @copydoc internal::ImplicitFunctionBase::Value
VTKM_EXEC_CONT Scalar Value(const Vector& point) const
{
Scalar maxVal = vtkm::NegativeInfinity<Scalar>();
@ -702,6 +772,8 @@ public:
}
return maxVal;
}
/// @copydoc internal::ImplicitFunctionBase::Gradient
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const
{
Scalar maxVal = vtkm::NegativeInfinity<Scalar>();
@ -792,11 +864,13 @@ public:
{
}
/// @copydoc internal::ImplicitFunctionBase::Value
VTKM_EXEC_CONT Scalar Value(const Vector& point) const
{
return this->Variant.CastAndCall(detail::ImplicitFunctionValueFunctor{}, point);
}
/// @copydoc internal::ImplicitFunctionBase::Gradient
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const
{
return this->Variant.CastAndCall(detail::ImplicitFunctionGradientFunctor{}, point);
@ -804,7 +878,7 @@ public:
};
//============================================================================
/// \brief Implicit function that can switch among known implicit function types.
/// @brief Implicit function that can switch among known implicit function types.
///
/// `ImplicitFunctionGeneral` can behave as any of the predefined implicit functions
/// provided by VTK-m. This is helpful when the type of implicit function is not
@ -817,6 +891,9 @@ public:
/// function that you want to use, and then set the `ImplicitFunctionGeneral`
/// to that concrete implicit function object.
///
/// `ImplicitFunctionGeneral` currently supports `vtkm::Box`, `vtkm::Cylinder`,
/// `vtkm::Frustum`, `vtkm::Plane`, and `vtkm::Sphere`.
///
class ImplicitFunctionGeneral
: public vtkm::ImplicitFunctionMultiplexer<vtkm::Box,
vtkm::Cylinder,

@ -35,7 +35,9 @@ class RecombineVec
vtkm::VecCConst<PortalType> Portals;
vtkm::Id Index;
/// @cond NOPE
friend vtkm::internal::ArrayPortalRecombineVec<PortalType>;
/// @endcond
public:
using ComponentType = typename std::remove_const<typename PortalType::ValueType>::type;

@ -490,6 +490,7 @@ struct StorageTagStride;
} // vtkm::cont
//-------------------------------------------------------------------------------------------------
/// @cond NOPE
VTKM_INSTANTIATION_BEGIN
VTK_M_ARRAY_RANGE_COMPUTE_ALL_SCALARS(extern template VTKM_CONT_TEMPLATE_EXPORT,
vtkm::cont::StorageTagBasic);
@ -624,5 +625,6 @@ VTKM_INSTANTIATION_BEGIN
VTK_M_ARRAY_RANGE_COMPUTE_ALL_SCALARS(extern template VTKM_CONT_TEMPLATE_EXPORT,
vtkm::cont::StorageTagStride);
VTKM_INSTANTIATION_END
/// @endcond
#endif //vtk_m_cont_ArrayRangeComputeTemplate_h

@ -21,6 +21,10 @@ namespace vtkm
namespace cont
{
/// @brief Defines the topological structure of the data in a `DataSet`.
///
/// Fundamentally, any cell set is a collection of cells, which typically (but not always)
/// represent some region in space.
class VTKM_CONT_EXPORT CellSet
{
public:
@ -33,23 +37,37 @@ public:
virtual ~CellSet();
/// @brief Get the number of cells in the topology.
virtual vtkm::Id GetNumberOfCells() const = 0;
virtual vtkm::Id GetNumberOfFaces() const = 0;
virtual vtkm::Id GetNumberOfEdges() const = 0;
/// @brief Get the number of points in the topology.
virtual vtkm::Id GetNumberOfPoints() const = 0;
/// @brief Get the shell shape of a particular cell.
virtual vtkm::UInt8 GetCellShape(vtkm::Id id) const = 0;
/// @brief Get the number of points incident to a particular cell.
virtual vtkm::IdComponent GetNumberOfPointsInCell(vtkm::Id id) const = 0;
/// @brief Get a list of points incident to a particular cell.
virtual void GetCellPointIds(vtkm::Id id, vtkm::Id* ptids) const = 0;
/// @brief Return a new `CellSet` that is the same derived class.
virtual std::shared_ptr<CellSet> NewInstance() const = 0;
/// @brief Copy the provided `CellSet` into this object.
///
/// The provided `CellSet` must be the same type as this one.
virtual void DeepCopy(const CellSet* src) = 0;
/// @brief Print a summary of this cell set.
virtual void PrintSummary(std::ostream&) const = 0;
/// @brief Remove the `CellSet` from any devices.
///
/// Any memory used on a device to store this object will be deleted.
/// However, the data will still remain on the host.
virtual void ReleaseResourcesExecution() = 0;
};

@ -66,6 +66,10 @@ VTKM_CONT_EXPORT void BuildReverseConnectivity(
#define VTKM_DEFAULT_OFFSETS_STORAGE_TAG VTKM_DEFAULT_STORAGE_TAG
#endif
/// @brief Defines an irregular collection of cells.
///
/// The cells can be of different types and connected in arbitrary ways.
/// This is done by explicitly providing for each cell a sequence of points that defines the cell.
template <typename ShapesStorageTag = VTKM_DEFAULT_SHAPES_STORAGE_TAG,
typename ConnectivityStorageTag = VTKM_DEFAULT_CONNECTIVITY_STORAGE_TAG,
typename OffsetsStorageTag = VTKM_DEFAULT_OFFSETS_STORAGE_TAG>
@ -146,17 +150,25 @@ public:
VTKM_CONT void GetIndices(vtkm::Id index, vtkm::cont::ArrayHandle<vtkm::Id>& ids) const;
/// First method to add cells -- one at a time.
/// @brief Start adding cells one at a time.
///
/// After this method is called, `AddCell` is called repeatedly to add each cell.
/// Once all cells are added, call `CompleteAddingCells`.
VTKM_CONT void PrepareToAddCells(vtkm::Id numCells, vtkm::Id connectivityMaxLen);
/// @brief Add a cell.
///
/// This can only be called after `AddCell`.
template <typename IdVecType>
VTKM_CONT void AddCell(vtkm::UInt8 cellType, vtkm::IdComponent numVertices, const IdVecType& ids);
/// @brief Finish adding cells one at a time.
VTKM_CONT void CompleteAddingCells(vtkm::Id numPoints);
/// Second method to add cells -- all at once.
/// Assigns the array handles to the explicit connectivity. This is
/// the way you can fill the memory from another system without copying
/// @brief Set all the cells of the mesh.
///
/// This method can be used to fill the memory from another system without
/// copying data.
VTKM_CONT
void Fill(vtkm::Id numPoints,
const vtkm::cont::ArrayHandle<vtkm::UInt8, ShapesStorageTag>& cellTypes,

@ -46,6 +46,13 @@ struct CellSetExtrudeConnectivityChooser<vtkm::TopologyElementTagPoint,
} // namespace detail
/// @brief Defines a 3-dimensional extruded mesh representation.
///
/// `CellSetExtrude` takes takes a mesh defined in the XZ-plane and extrudes it along
/// the Y-axis. This plane is repeated in a series of steps and forms wedge cells
/// between them.
///
/// The extrusion can be linear or rotational (e.g., to form a torus).
class VTKM_CONT_EXPORT CellSetExtrude : public CellSet
{
public:

@ -309,6 +309,16 @@ struct CellSetPermutationConnectivityChooser<vtkm::TopologyElementTagPoint,
} // internal
/// @brief Rearranges the cells of one cell set to create another cell set.
///
/// This restructuring of cells is not done by copying data to a new structure.
/// Rather, `CellSetPermutation` establishes a look-up from one cell structure to
/// another. Cells are permuted on the fly while algorithms are run.
///
/// A `CellSetPermutation` is established by providing a mapping array that for every
/// cell index provides the equivalent cell index in the cell set being permuted.
/// `CellSetPermutation` is most often used to mask out cells in a data set so that
/// algorithms will skip over those cells when running.
template <typename OriginalCellSetType_,
typename PermutationArrayHandleType_ =
vtkm::cont::ArrayHandle<vtkm::Id, VTKM_DEFAULT_CELLSET_PERMUTATION_STORAGE_TAG>>
@ -324,17 +334,21 @@ public:
using OriginalCellSetType = OriginalCellSetType_;
using PermutationArrayHandleType = PermutationArrayHandleType_;
VTKM_CONT
CellSetPermutation(const PermutationArrayHandleType& validCellIds,
const OriginalCellSetType& cellset)
/// @brief Create a `CellSetPermutation`.
///
/// @param[in] validCellIds An array that defines the permutation. If index @a i
/// is value @a j, then the @a ith cell of this cell set will be the same as
/// the @a jth cell in the original @a cellset.
/// @param[in] cellset The original cell set that this one is permuting.
VTKM_CONT CellSetPermutation(const PermutationArrayHandleType& validCellIds,
const OriginalCellSetType& cellset)
: CellSet()
, ValidCellIds(validCellIds)
, FullCellSet(cellset)
{
}
VTKM_CONT
CellSetPermutation()
VTKM_CONT CellSetPermutation()
: CellSet()
, ValidCellIds()
, FullCellSet()
@ -358,9 +372,11 @@ public:
return *this;
}
/// @brief Returns the original `CellSet` that this one is permuting.
VTKM_CONT
const OriginalCellSetType& GetFullCellSet() const { return this->FullCellSet; }
/// @brief Returns the array used to permute the cell indices.
VTKM_CONT
const PermutationArrayHandleType& GetValidCellIds() const { return this->ValidCellIds; }
@ -426,7 +442,12 @@ public:
vtkm::cont::ArrayCopy(other->GetValidCellIds(), this->ValidCellIds);
}
//This is the way you can fill the memory from another system without copying
/// @brief Set the topology.
///
/// @param[in] validCellIds An array that defines the permutation. If index @a i
/// is value @a j, then the @a ith cell of this cell set will be the same as
/// the @a jth cell in the original @a cellset.
/// @param[in] cellset The original cell set that this one is permuting.
VTKM_CONT
void Fill(const PermutationArrayHandleType& validCellIds, const OriginalCellSetType& cellset)
{

Some files were not shown because too many files have changed in this diff Show More