Modules | C++

Iso

Scalar field crossings, isocontours, isocurve embedding, and isobands.

The Iso module is the scalar field pipeline. It is driven by field crossings rather than by polygon intersections, so it is a tier of its own: the crossings a field states on a mesh, the curves they trace, and the mesh recut so those curves are edges.

Include the module with:

#include <trueform/iso.hpp>

Isocontours

Extract curves where a scalar field crosses threshold values.

Single Isocontour

isocontour.cpp
std::vector<float> scalar_field(mesh.points().size());
// Assign scalar values to vertices...

float threshold = 0.5f;
auto contour = tf::make_isocontours(mesh.polygons(), tf::make_range(scalar_field), threshold);

Multiple Isocontours

multi_isocontours.cpp
std::vector<float> levels = {0.0f, 0.25f, 0.5f, 0.75f, 1.0f};
auto contours = tf::make_isocontours(mesh.polygons(), tf::make_range(scalar_field), tf::make_range(levels));

Embedded Isocurves

Isocurves are level sets of a scalar field. Embedding them creates a mesh where contour lines become edges:

embedded_isocurves.cpp
tf::buffer<float> scalar_field;
scalar_field.allocate(mesh.points().size());
// Assign scalar values to vertices...

std::array<float, 3> cut_values = {0.0f, 0.5f, 1.0f};

auto [result, labels, face_labels] = tf::embedded_isocurves(
    mesh.polygons(),
    tf::make_range(scalar_field),
    tf::make_range(cut_values));

// With curves
auto [result, labels, face_labels, curves] = tf::embedded_isocurves(
    mesh.polygons(),
    tf::make_range(scalar_field),
    tf::make_range(cut_values),
    tf::return_curves);

The labels buffer contains one integer per face, indicating which isoband the face belongs to. Labels 0, 1, 2, ... correspond to regions (-∞, cut_values[0]), [cut_values[0], cut_values[1]), etc.

Isobands

While embedded_isocurves creates a mesh with all regions, make_isobands extracts only selected bands:

isobands.cpp
std::array<float, 4> cut_values = {0.0f, 0.25f, 0.5f, 0.75f};
std::array<int, 2> selected_bands = {1, 3};

auto [result, labels, face_labels] = tf::make_isobands(
    mesh.polygons(),
    tf::make_range(scalar_field),
    tf::make_range(cut_values),
    tf::make_range(selected_bands));

Refused Faces

A cut face the triangulation declines holds no piece in any band, so its surface is simply absent from the result — emptiness is always the answer. Both emitters take tf::return_refused to also receive, ascending, the ids of those faces:

iso_refused.cpp
auto [result, labels, face_labels, refused] = tf::embedded_isocurves(
    mesh.polygons(),
    tf::make_range(scalar_field),
    tf::make_range(cut_values),
    tf::return_refused);

auto [bands, band_labels, band_face_labels, band_refused] = tf::make_isobands(
    mesh.polygons(),
    tf::make_range(scalar_field),
    tf::make_range(cut_values),
    tf::make_range(selected_bands),
    tf::return_refused);
ParameterTypeDescription
tf::return_refusedtf::return_refused_tTag requesting the refused ids

The mesh, labels and face labels are exactly the ones the untagged call returns, and the ids are face ids of the input mesh — an isoband call reports the whole mesh's, since a face the cut declined holds no piece in any band. The one-chord split cannot refuse and a constraint set the field states on a face it crosses is recoverable, so the list speaks only on degenerate input.

Scalar Field Intersections

Low-level access to isosurface intersection data.

tf::scalar_field_intersections stores its points in the input's own floating-point coordinates.
scalar_field_low_level.cpp
tf::scalar_field_intersections<int, float, 3> sfi;
sfi.build(mesh.polygons(), scalar_field, threshold);

auto points = sfi.intersection_points();

for (auto group : sfi.intersections()) {
    for (auto intersection : group) {
        intersection.object;        // Face ID
        intersection.id;            // Point ID
        intersection.target.label;  // vertex/edge where crossing occurs
        intersection.target.id;     // Local index
    }
}

// Multiple thresholds
sfi.build_many(mesh.polygons(), scalar_field, thresholds);