Common operations in trueform vs established geometry libraries. The key difference: trueform operates directly on polygon arrays without intermediate mesh structures.
CGAL requires converting to Surface_mesh and using property maps:
#include <CGAL/Polygon_mesh_processing/connected_components.h>
#include <CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h>
namespace PMP = CGAL::Polygon_mesh_processing;
// Convert polygon soup to CGAL mesh structure
Surface_mesh mesh;
PMP::polygon_soup_to_polygon_mesh(points, faces, mesh);
// Compute connected components
std::vector<std::size_t> face_cc(num_faces(mesh));
auto n_components = PMP::connected_components(mesh, CGAL::make_property_map(face_cc));
trueform operates directly on polygon arrays:
#include <trueform/trueform.hpp>
auto [labels, n_components] =
tf::make_manifold_edge_connected_component_labels(polygons);
CGAL requires mesh conversion and copies for corefinement:
#include <CGAL/Polygon_mesh_processing/corefinement.h>
// Convert to CGAL mesh
auto mesh1 = to_cgal_mesh(polygons);
auto mesh2 = to_cgal_mesh(transformed_polygons);
// Corefinement mutates inputs—copy first
Surface_mesh mesh1_copy = mesh1;
Surface_mesh mesh2_copy = mesh2;
Surface_mesh result;
PMP::corefine_and_compute_union(mesh1_copy, mesh2_copy, result);
trueform composes forms with lazy transformations:
#include <trueform/trueform.hpp>
tf::frame<float, 3> frame = tf::make_frame(rotation);
auto result = tf::make_boolean(polygons0, polygons1 | tf::tag(frame) , tf::boolean_op::merge);
The benchmarks also compare boundary path extraction, polygon tree construction, closest point queries, and mesh-mesh intersection curves. Sources: topology, spatial, cut, intersect.
nanoflann requires an adapter class:
#include <nanoflann.hpp>
// Adapter to expose point data
template <typename Real, int Dims>
struct PointCloudAdapter {
const Real* data;
size_t n_points;
size_t kdtree_get_point_count() const { return n_points; }
Real kdtree_get_pt(size_t idx, size_t dim) const {
return data[idx * Dims + dim];
}
template <class BBOX> bool kdtree_get_bbox(BBOX&) const { return false; }
};
using Adapter = PointCloudAdapter<float, 3>;
using KDTree = nanoflann::KDTreeSingleIndexAdaptor<
nanoflann::L2_Simple_Adaptor<float, Adapter>, Adapter, 3>;
Adapter adapter(points_data, n_points);
KDTree tree(3, adapter, {4});
// Query
std::vector<size_t> indices(k);
std::vector<float> distances(k);
nanoflann::KNNResultSet<float> result_set(k);
result_set.init(&indices[0], &distances[0]);
tree.findNeighbors(result_set, &query_point[0], {});
trueform uses a uniform interface:
#include <trueform/trueform.hpp>
tf::aabb_tree<int, float, 3> tree;
tree.build(points, tf::config_tree(4, 4));
auto form = points | tf::tag(tree);
// Query
std::array<tf::nearest_neighbor<int, float, 3>, 10> buffer;
auto knn = tf::make_nearest_neighbors(buffer.begin(), k);
tf::neighbor_search(form, query_point, knn);
// Results in knn[0..k-1]
for (auto& nn : knn) {
// nn.element (index), nn.info.metric (squared distance), nn.info.point
}
Tree types are interchangeable—aabb_tree, obb_tree, obbrss_tree all use the same query API.
The benchmarks also compare tree construction times. Sources: spatial.
libigl uses Eigen matrices:
#include <igl/facet_components.h>
// Face indices as Eigen matrix
Eigen::MatrixXi F = to_eigen_faces(faces);
// Compute components
Eigen::VectorXi C;
igl::facet_components(F, C);
// C[i] = component label for face i
trueform works with native arrays:
#include <trueform/trueform.hpp>
auto [labels, n_components] =
tf::make_manifold_edge_connected_component_labels(polygons);
// labels[i] = component label for face i
The benchmarks also compare boundary path extraction, isocontour generation, boolean operations, and self-intersection detection. Sources: topology, intersect, cut.
For VTK integration, trueform provides tf::vtk—an extended vtkPolyData with cached acceleration structures, zero-copy views, and VTK pipeline filters.
#include <trueform/vtk.hpp>
auto mesh = vtkSmartPointer<tf::vtk::polydata>::New();
mesh->ShallowCopy(reader->GetOutput());
// Iterate as trueform primitives
for (auto polygon : mesh->polygons()) { /* ... */ }
// Use trueform algorithms
auto [result, curves] = tf::vtk::make_boolean(mesh0, mesh1, tf::boolean_op::merge);
The benchmarks compare connected components, boundary paths, isocontours, mesh-mesh intersection curves, and embedded isocurves. Sources: topology, intersect, cut.