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.
Enable VTK integration when building trueform:
cmake -DBUILD_VTK=ON ..
make trueform_vtk -j10
Requires VTK 9+ with CommonCore and CommonDataModel components.
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.