VTK | C++

Overview

VTK integration layer for trueform algorithms.

The tf::vtk library integrates trueform with VTK (Visualization Toolkit). It provides tf::vtk::polydata—an extended vtkPolyData with cached acceleration structures—plus standalone functions and VTK pipeline filters wrapping trueform's algorithms. Use trueform's performance in existing VTK applications with zero-copy data access.

Building

Enable VTK integration when building trueform:

cmake -DBUILD_VTK=ON ..
make trueform_vtk -j10

Requires VTK 9+ with CommonCore and CommonDataModel components.

Core

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

Functions

Standalone functions for booleans, spatial queries, and more.

Filters

VTK pipeline filters wrapping trueform algorithms.

Examples

Interactive applications: collision, booleans, isocontours.

Quick Tour

Wrap any vtkPolyData to access trueform's API:

#include <trueform/vtk.hpp>

// Your existing VTK pipeline
vtkNew<vtkSTLReader> reader;
reader->SetFileName("model.stl");
reader->Update();

// Wrap in tf::vtk::polydata (zero-copy)
auto mesh = vtkSmartPointer<tf::vtk::polydata>::New();
mesh->ShallowCopy(reader->GetOutput());

Iterate over geometry as trueform primitive views:

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

// Polygons (faces + points) - dynamic size
for (auto polygon : mesh->polygons()) {
    for (auto pt : polygon) {
        // each pt is a tf::point_view<float, 3>
    }
    // Access vertex indices
    for (auto id : polygon.indices()) {
        // id is vtkIdType
    }
}

// Lines/paths
for (auto curve : mesh->curves()) {
    for (auto pt : curve) {
        // each pt is a tf::point_view<float, 3>
    }
    for (auto id : curve.indices()) {
        // point index along the path
    }
}

Use trueform functions directly on the views:

auto polygons = polydata0->polygons();
// segments of lines
auto segments = polydata1->segments();

if(!tf::intersects(segments[0], polygons[10])) {
    auto d2 = tf::distance2(segments[0], polygons[10]);
}

Cached acceleration structures are built lazily and track VTK's MTime:

// First access builds the structure
auto& tree = mesh->poly_tree();           // tf::aabb_tree
auto& point_tree = mesh->point_tree();           // tf::aabb_tree
auto& fm = mesh->face_membership();       // tf::face_membership
auto& mel = mesh->manifold_edge_link();   // tf::manifold_edge_link

// Subsequent accesses reuse cached structures
// Structures rebuild automatically when mesh data changes

Collision detection and distance between meshes:

// Check if two meshes intersect
if (tf::vtk::intersects(mesh0, mesh1)) {
    // handle collision
}

// Get squared distance between meshes
auto d2 = tf::vtk::distance2(mesh0, mesh1);

// Get actual distance
auto d = tf::vtk::distance(mesh0, mesh1);

// Full nearest neighbor info between meshes
auto nearest = tf::vtk::neighbor_search(mesh0, mesh1);
// nearest.elements.first, nearest.elements.second - primitive indices
// nearest.info.metric - squared distance
// nearest.info.first, nearest.info.second - closest points

Spatial queries work directly on polydata:

auto ray = tf::make_ray(origin, direction);
if (auto hit = tf::vtk::ray_hit(ray, mesh)) {
    // hit.element, hit.info.t, hit.info.point
}

auto query_pt = tf::point<float, 3>{1.0f, 2.0f, 3.0f};
if (auto nearest = tf::vtk::neighbor_search(mesh, query_pt)) {
    // nearest.element, nearest.info.metric, nearest.info.point
}

// k nearest neighbors
auto knn = tf::vtk::neighbor_search_k(mesh, query_pt, 5);
for (auto& neighbor : knn) {
    // neighbor.element, neighbor.info.metric, neighbor.info.point
}

Boolean operations between meshes:

auto [result, curves] = tf::vtk::make_boolean(
    mesh1, mesh2, tf::boolean_op::merge, tf::return_curves);

// Result is tf::vtk::polydata with "Labels" cell scalars
for (auto polygon : result->polygons()) {
    // ...
}

VTK pipeline filters integrate with existing pipelines:

// Adapter converts vtkPolyData → tf::vtk::polydata
vtkNew<tf::vtk::adapter> adapter;
adapter->SetInputConnection(reader->GetOutputPort());

// Boolean filter
vtkNew<tf::vtk::boolean> boolean_filter;
boolean_filter->SetInputConnection(0, adapter1->GetOutputPort());
boolean_filter->SetInputConnection(1, adapter2->GetOutputPort());
boolean_filter->set_operation(tf::boolean_op::merge);
boolean_filter->Update();

auto* result = boolean_filter->GetOutput();

This is tf::vtk from a bird's eye view. For detailed API documentation, explore the Core utilities, Functions reference, and Filters guide.