VTK | C++

Core

Polydata, zero-copy views, and data conversion utilities.

The core module bridges VTK and trueform. It provides zero-copy views that expose VTK data through trueform's semantic ranges—tf::points, tf::polygons, tf::curves, and more—so you get the same ease of use and composability on VTK objects. Conversion utilities handle the reverse direction, turning trueform buffers back into VTK objects. The tf::vtk::polydata class extends vtkPolyData with cached acceleration structures for repeated queries.

Include the module with:

#include <trueform/vtk/core.hpp>

tf::vtk::polydata

A vtkPolyData subclass that adds lazy-built, MTime-tracked acceleration structures. Structures rebuild automatically when the underlying mesh data changes.

Creation

// Create new polydata
auto mesh = vtkSmartPointer<tf::vtk::polydata>::New();

// Wrap existing vtkPolyData (zero-copy)
mesh->ShallowCopy(reader->GetOutput());

// Detect in VTK pipelines
if (auto* tf_poly = tf::vtk::polydata::SafeDownCast(input)) {
    // Use cached structures
}

// Retrieve from filter input (creates if needed)
auto* poly = tf::vtk::polydata::GetData(inputVector, 0);

Geometry Views

Access mesh data as trueform views. See Primitive Ranges and Views for details on each type.

points()

Returns a tf::points view over the mesh vertices. Each element is a tf::point_view.

for (auto pt : mesh->points()) {
    auto [x, y, z] = pt;
}

polys()

Returns a tf::offset_block_range view over face connectivity. Each element is a variable-length block of vertex indices.

for (auto face : mesh->polys()) {
    for (auto vertex_id : face) { /* ... */ }
}

polygons()

Returns a tf::polygons view combining face indices with point coordinates. Each element is a tf::polygon providing both geometry and indices.

for (auto polygon : mesh->polygons()) {
    for (auto pt : polygon) { /* point_view */ }
    for (auto id : polygon.indices()) { /* vertex index */ }
}

paths()

Returns a tf::paths view over line connectivity. Each path is a variable-length sequence of vertex indices.

for (auto path : mesh->paths()) {
    for (auto vertex_id : path) { /* ... */ }
}

curves()

Returns a tf::curves view combining path indices with point coordinates. Each element is a curve providing both geometry and indices.

for (auto curve : mesh->curves()) {
    for (auto pt : curve) { /* point_view */ }
    for (auto id : curve.indices()) { /* vertex index */ }
}

edges() and segments()

Returns tf::edges and tf::segments views built from line data. Edges are pairs of vertex indices; each tf::segment combines an edge with point coordinates.

for (auto edge : mesh->edges()) {
    auto [v0, v1] = edge;
}

for (auto segment : mesh->segments()) {
    auto [pt0, pt1] = segment;
}

Normals

Returns tf::unit_vectors views over normal data. Each element is a tf::unit_vector_view. Empty if no normals are present.

auto pn = mesh->point_normals();
if (pn.size() > 0) {
    for (auto normal : pn) { /* unit_vector_view */ }
}

auto cn = mesh->cell_normals();

Cached Structures

All structures are built lazily on first access and cached. They automatically rebuild when VTK's MTime indicates data has changed.

Spatial Trees

Returns tf::aabb_tree structures for accelerated spatial queries.

const auto& poly_tree = mesh->poly_tree();      // polygon bounding boxes
const auto& seg_tree = mesh->segment_tree();    // line segment bounding boxes
const auto& pt_tree = mesh->point_tree();       // point bounding boxes

Topology Structures

Returns connectivity structures from the Topology module.

MethodReturnsDescription
face_membership()tf::face_membershipFor each vertex, list of faces containing it
manifold_edge_link()tf::manifold_edge_linkEdge adjacency info (boundary, manifold status)
face_link()tf::face_linkFor each face, list of adjacent faces
vertex_link()tf::vertex_linkFor each vertex, list of neighboring vertices
const auto& fm = mesh->face_membership();
const auto& mel = mesh->manifold_edge_link();
const auto& fl = mesh->face_link();
const auto& vl = mesh->vertex_link();

Edge Buffer

Returns a tf::blocked_buffer of edge pairs extracted from line data.

const auto& edges = mesh->edges_buffer();  // tf::blocked_buffer<vtkIdType, 2>

VTK → trueform Views

Zero-copy views over VTK data. These functions wrap VTK memory without copying—the returned views are valid only while the source VTK object exists. Once wrapped, you can use trueform's full API: iterate, query, pass to algorithms.

Geometry

Wrap VTK geometry as trueform ranges. Use the dynamic variants for mixed meshes (tri/quad/n-gon), or the sized variants when the topology is uniform.

FactoryInputReturnsElement
make_pointsvtkPoints* or vtkPolyData*points_ttf::point_view
make_polysvtkCellArray*polys_ttf::range<vtkIdType*, tf::dynamic_size>
make_polys<V>vtkCellArray*polys_sized_t<V>tf::range<vtkIdType*, V>
make_polygonsvtkPolyData*polygons_ttf::polygon
make_polygons<V>vtkPolyData*polygons_sized_t<V>tf::polygon
make_pathsvtkCellArray*paths_ttf::range<vtkIdType*, tf::dynamic_size>
make_curvesvtkPolyData*curves_ttf::curve
make_linesvtkCellArray*lines_ttf::range<vtkIdType*, tf::dynamic_size>
make_lines<V>vtkCellArray*lines_sized_t<V>tf::range<vtkIdType*, V>
// Points from vtkPolyData
auto points = tf::vtk::make_points(polydata);

// Polygons (dynamic size - handles mixed tri/quad/n-gon)
auto polygons = tf::vtk::make_polygons(polydata);

// Triangles only (compile-time size)
auto triangles = tf::vtk::make_polygons<3>(polydata);

// Curves from line data
auto curves = tf::vtk::make_curves(polydata);

Normals

FactoryInputReturnsElement
make_point_normalsvtkPolyData*normals_ttf::unit_vector_view
make_cell_normalsvtkPolyData*normals_ttf::unit_vector_view
auto point_normals = tf::vtk::make_point_normals(polydata);
auto cell_normals = tf::vtk::make_cell_normals(polydata);
// Returns empty view if no normals present

Arrays

Wrap VTK arrays as trueform ranges for scalar fields, per-vertex attributes, or any array data.

FactoryInputReturnsElement
make_rangevtkFloatArray*float_range_tfloat
make_rangevtkDoubleArray*double_range_tdouble
make_rangevtkIntArray*int_range_tint
make_rangevtkIdTypeArray*vtkIdType_range_tvtkIdType
make_blocked_range<V>vtk*Array*blocked range (static)tf::range<T*, V>
make_blocked_rangevtk*Array*, sizeblocked range (dynamic)tf::range<T*, tf::dynamic_size>
make_byte_blocksvtkDataArray*byte_blocks_ttf::range<unsigned char*, tf::dynamic_size>
// Flat range over array data
auto scalars = tf::vtk::make_range(floatArray);

// Blocked access (e.g., RGB tuples)
auto colors = tf::vtk::make_blocked_range<3>(colorArray);

// Dynamic block size
auto tuples = tf::vtk::make_blocked_range(array, tuple_size);

// Raw byte access per tuple
auto bytes = tf::vtk::make_byte_blocks(dataArray);

trueform → VTK Buffers

After processing with trueform algorithms, convert results back to VTK objects. All functions have two overloads:

  • const& - copies data
  • && - moves data (zero-copy when possible)

Geometry

Convert trueform geometry buffers to vtkPolyData or its components.

FactoryInputOutput
make_vtk_pointstf::points_buffervtkSmartPointer<vtkPoints>
make_vtk_cellstf::blocked_buffervtkSmartPointer<vtkCellArray>
make_vtk_cellstf::offset_block_buffervtkSmartPointer<vtkCellArray>
make_vtk_polydatatf::polygons_buffervtkSmartPointer<vtkPolyData>
make_vtk_polydatatf::curves_buffervtkSmartPointer<vtkPolyData>
make_vtk_polydatatf::segments_buffervtkSmartPointer<vtkPolyData>
// From polygons buffer (move for zero-copy)
tf::polygons_buffer<vtkIdType, float, 3, tf::dynamic_size> result;
// ... fill result ...
auto polydata = tf::vtk::make_vtk_polydata(std::move(result));

// From curves buffer
tf::curves_buffer<vtkIdType, float, 3> curves;
// ... fill curves ...
auto lines = tf::vtk::make_vtk_polydata(std::move(curves));

Normals

FactoryInputOutput
make_vtk_normalstf::unit_vectors_buffervtkSmartPointer<vtkFloatArray>
auto normals = tf::compute_normals(polygons);
auto vtk_normals = tf::vtk::make_vtk_normals(std::move(normals));
vtk_normals->SetName("Normals");
polydata->GetCellData()->SetNormals(vtk_normals);

Arrays

FactoryInputOutput
make_vtk_arraytf::buffervtkSmartPointer<vtk*Array>
tf::buffer<int> labels;
// ... fill labels ...
auto vtk_labels = tf::vtk::make_vtk_array(std::move(labels));
vtk_labels->SetName("Labels");
polydata->GetCellData()->AddArray(vtk_labels);

Reindexing

When mesh topology changes (cleaning, boolean operations), point and cell data must be remapped. These utilities apply index maps to preserve VTK attributes through such operations.

FactoryInputOutput
make_vtk_array_reindexedvtkDataArray*, tf::index_map_buffervtkSmartPointer<vtkDataArray>
make_vtk_point_data_reindexedvtkPointData*, tf::index_map_buffervtkSmartPointer<vtkPointData>
make_vtk_cell_data_reindexedvtkCellData*, tf::index_map_buffervtkSmartPointer<vtkCellData>
tf::index_map_buffer<vtkIdType> point_map;
// ... build map during mesh cleaning ...

// Reindex all point data arrays
auto new_point_data = tf::vtk::make_vtk_point_data_reindexed(
    input->GetPointData(), point_map);
output->GetPointData()->ShallowCopy(new_point_data);

Transform Utilities

Convert between trueform transformations and VTK matrices. Use these when working with actor transforms or building world-space rays for picking.

FactoryInputOutput
make_framevtkMatrix4x4*tf::frame
fill_frametf::frame<T, 3>&, vtkMatrix4x4*void
make_vtk_matrixtf::transformation<T, 3>vtkSmartPointer<vtkMatrix4x4>
fill_vtk_matrixvtkMatrix4x4*, tf::transformation<T, 3>void
make_vtk_transformtf::transformation<T, 3>vtkSmartPointer<vtkTransform>
fill_vtk_transformvtkTransform*, tf::transformation<T, 3>void
make_world_rayvtkRenderer*, x, ytf::ray
// VTK matrix → trueform frame
auto frame = tf::vtk::make_frame(actor->GetUserMatrix());
auto form = tf::make_form(frame, mesh->poly_tree(), mesh->polygons());

// trueform transformation → VTK matrix
auto transform = tf::random_transformation<float, 3>();
auto matrix = tf::vtk::make_vtk_matrix(transform);
actor->SetUserMatrix(matrix);

// Update existing matrix
tf::vtk::fill_vtk_matrix(actor->GetUserMatrix(), new_transform);

// Screen-space picking ray
auto ray = tf::vtk::make_world_ray(renderer, mouse_x, mouse_y);
if (auto hit = tf::vtk::ray_hit(ray, mesh)) {
    // Process hit
}

Type Aliases

For convenience, the module provides type aliases for the most common view types. These match the return types of the factory functions above.

// Geometry views
using points_t = /* tf::points view over float data */;
using polys_t = /* tf::offset_block_range over vtkIdType */;
using polygons_t = /* tf::polygons (polys + points) */;
using paths_t = /* tf::paths view */;
using curves_t = /* tf::curves (paths + points) */;
using lines_t = /* tf::offset_block_range over vtkIdType */;
using edges_t = /* tf::edges view */;
using segments_t = /* tf::segments (edges + points) */;
using normals_t = /* tf::unit_vectors view */;

// Sized variants (compile-time vertex count)
template<std::size_t V> using polys_sized_t = /* ... */;
template<std::size_t V> using polygons_sized_t = /* ... */;
template<std::size_t V> using lines_sized_t = /* ... */;

// Array ranges
using float_range_t = tf::range<float*, tf::dynamic_size>;
using double_range_t = tf::range<double*, tf::dynamic_size>;
using int_range_t = tf::range<int*, tf::dynamic_size>;
using vtkIdType_range_t = tf::range<vtkIdType*, tf::dynamic_size>;