These examples provide direct performance comparisons with established geometry processing libraries, demonstrating the efficiency of trueform's data structures and algorithms. Detailed benchmark results and performance analysis are available at /benchmarks.
Source: nanoflann/knn.cpp
Direct performance benchmark for k-Nearest Neighbor queries, comparing tf::tree against nanoflann's KD-tree implementation.
tf::tree and nanoflann::KDTree from the same data source// Build trueform tree
tf::aabb_tree<int, float, 3> tf_tree(points, tf::config_tree(4, 4));
auto form = tf::make_form(tf_tree, points);
// Build nanoflann tree
using KDTree = nanoflann::KDTreeSingleIndexAdaptor<
nanoflann::L2_Simple_Adaptor<float, PointCloudAdaptor>,
PointCloudAdaptor, 3>;
KDTree nano_tree(3, adaptor, {10});
// Benchmark trueform
auto query_pt = tf::random_point<float, 3>();
std::array<tf::nearest_neighbor<int, float, 3>, 10> buffer;
tf::tick();
auto knn = tf::make_nearest_neighbors(buffer.begin(), 10);
tf::neighbor_search(form, query_pt, knn);
auto tf_time = tf::tock();
// Benchmark nanoflann
std::vector<size_t> indices(10);
std::vector<float> distances(10);
tf::tick();
nano_tree.knnSearch(query_pt.data(), 10,
indices.data(), distances.data());
auto nano_time = tf::tock();
std::cout << "Speedup: " << (nano_time / tf_time) << "x" << std::endl;
Source: cgal/intersecting_primitives.cpp
Direct comparison for collecting intersecting primitives between two meshes.
all_intersecting_primitives returns only primitives on the first mesh that intersect any primitive on the second mesh, while trueform's tf::gather_ids returns all intersecting primitive pairs. Trueform does more work in less time.tf::tree acceleration structuretf::tree via tf::formtf::gather_ids for efficient pair collection// Build forms
auto form0 = tf::make_form(tree, mesh.polygons());
auto form1 = tf::make_form(
tf::make_frame(transform), tree, mesh.polygons());
// Collect all intersecting pairs
std::vector<std::pair<int, int>> pairs;
tf::gather_ids(form0, form1, tf::intersects_f,
std::back_inserter(pairs));
Source: cgal/intersection_curve.cpp
Direct comparison for computing intersection curves between two transforming meshes.
tf::intersections_between_polygons to compute intersectionstf::make_intersection_edgestf::face_membership and tf::manifold_edge_linkpoints.as<double>() for type conversion views// Build topology
tf::face_membership<int> fm1, fm2;
fm1.build(mesh1.polygons());
fm2.build(mesh2.polygons());
tf::manifold_edge_link<int, 3> mel1, mel2;
mel1.build(mesh1.faces(), fm1);
mel2.build(mesh2.faces(), fm2);
// Create forms with topology tags
auto form1 = tf::make_form(tree1,
mesh1.polygons() | tf::tag(mel1) | tf::tag(fm1));
auto form2 = tf::make_form(tree2,
mesh2.polygons() | tf::tag(mel2) | tf::tag(fm2));
// Compute intersections
tf::intersections_between_polygons<int, double, 3> ibp;
ibp.build(form1, form2);
// Extract intersection edges
auto edges = tf::make_intersection_edges(ibp);
auto segments = tf::make_segments(edges,
ibp.intersection_points());
Source: cgal/planar_arrangments.cpp
Direct comparison for computing planar arrangements from an unordered collection of 2D line segments.
tf::planar_arrangements to extract oriented faces and hole relationstf::make_edges and tf::make_points for semantic ranges// Build planar arrangement
tf::planar_arrangements<int, float> pa;
pa.build(segments);
// Access faces and holes
for (auto [face, hole_ids] :
tf::zip(pa.faces(), pa.holes_for_faces())) {
auto polygon = tf::make_polygon(face, pa.points());
for (auto hole : tf::make_indirect_range(hole_ids, pa.holes())) {
auto hole_polygon = tf::make_polygon(hole, pa.points());
// Process hole
}
}
Source: cgal/connected_components.cpp
Direct comparison for labeling connected components in a mesh.
tf::label_connected_components with custom connectivity rulestf::make_applier to define traversal patterns// Build connectivity structures
tf::face_membership<int> fm;
tf::manifold_edge_link<int, 3> mel;
fm.build(polygons);
mel.build(polygons.faces(), fm);
// Label components
tf::buffer<int> labels;
labels.allocate(polygons.size());
auto component_count = tf::label_connected_components<int>(
labels,
tf::make_applier(mel) // Only traverse manifold edges
);
std::cout << "Found " << component_count
<< " connected components" << std::endl;
Source: cgal/cgal-boolean.cpp
Direct comparison for computing boolean operations (union, intersection, difference) between two meshes.
tf::make_boolean for set operations// Create forms with topology
auto form1 = tf::make_form(tree1,
mesh1.polygons() | tf::tag(mel1) | tf::tag(fm1));
auto form2 = tf::make_form(tree2,
mesh2.polygons() | tf::tag(mel2) | tf::tag(fm2));
// Compute boolean union
auto [result_mesh, labels, curves] = tf::make_boolean(
form1, form2,
tf::boolean_op::merge,
tf::return_curves
);
std::cout << "Result: " << result_mesh.faces().size()
<< " faces" << std::endl;
std::cout << "Intersection curves: " << curves.size()
<< " paths" << std::endl;
merge (union), intersection, left_difference (A \ B), right_difference (B \ A)Source: vtk/feature_edges.cpp
Direct performance benchmark for extracting boundary and non-manifold edges.
tf::make_boundary_edges for boundary extractiontf::make_non_manifold_edges for topology analysis// Extract boundary edges
auto boundary_edges = tf::make_boundary_edges(polygons);
std::cout << "Boundary edges: " << boundary_edges.size() / 2
<< std::endl;
// Extract non-manifold edges
auto non_manifold_edges = tf::make_non_manifold_edges(polygons);
std::cout << "Non-manifold edges: " << non_manifold_edges.size() / 2
<< std::endl;
// With pre-computed topology
tf::face_membership<int> fm;
fm.build(polygons);
auto boundary = tf::make_boundary_edges(polygons | tf::tag(fm));
auto non_manifold = tf::make_non_manifold_edges(polygons | tf::tag(fm));
Source: vtk/compare_clean.cpp
Direct performance benchmark for cleaning meshes with specified tolerance. Trueform's implementation additionally removes all unreferenced points.
tf::cleaned for tolerance-based duplicate removal// Clean mesh with tolerance
float tolerance = 1e-6f;
auto [clean_mesh, face_map, point_map] =
tf::cleaned<int>(polygons, tolerance, tf::return_index_map);
std::cout << "Original: " << polygons.size() << " faces, "
<< polygons.points().size() << " points" << std::endl;
std::cout << "Cleaned: " << clean_mesh.faces().size() << " faces, "
<< clean_mesh.points().size() << " points" << std::endl;
// Reindex associated data
auto clean_normals = tf::reindexed(face_normals, face_map);
auto clean_attributes = tf::reindexed(point_attributes, point_map);
Source: vtk/vtk_intersection_curve.cpp
Direct comparison for computing intersection curves between two transforming meshes.
tf::intersections_between_polygons with formstf::face_membership and tf::manifold_edge_link topology tagspoints.as<double>()