Modules | PY

Intersect

Exact mesh intersections, self-intersections, and scalar field isocontours.

The Intersect module computes geometric intersections between meshes and scalar fields. All intersection computations are geometrically and topologically exact, using exact arithmetic.

import trueform as tf

Overview

The Intersect module computes intersection geometry without modifying the input meshes:

  • Mesh-mesh intersections: Curves where two or more meshes intersect
  • Self-intersections: Curves where a mesh intersects itself
  • Scalar field intersections: Contour curves at threshold values

Curves are returned as (paths, points) tuples where paths is an OffsetBlockedArray of index sequences and points is a numpy array of coordinates.

To embed intersection curves into mesh topology (splitting faces along curves), use the Cut module.

Supported Input

Intersection computation supports a wide range of input geometry:

  • Open and closed meshes — boundaries are handled correctly
  • Non-manifold edges — edges shared by 3 or more faces
  • Coplanar faces — overlapping faces from the same or different meshes
  • Self-intersecting geometry — meshes that intersect themselves are detected and curves are extracted
  • Crossing intersection curves — where curves from different mesh pairs meet on a face, crossings can be resolved by splitting curves at the crossing point. Configured via the mode, tolerance, resolve_crossings, and resolve_self_crossings keyword arguments — see Intersection Configuration.
For detecting where a single mesh intersects itself, use tf.self_intersection_curves.

Intersection Configuration

All intersection and arrangement functions accept the same configuration as keyword-only arguments. They map to the C++ tf::intersect_config (mode + tolerance) extended with the contour-crossing flags.

Mode

The mode parameter selects the base intersection strategy:

ModeDescription
"sos"SoS (Simulation of Simplicity) perturbation. Fast, no degenerate cases.
"primitives"Full 5-type classification. Handles shared edges, shared vertices, and coplanar faces.

Contour crossing resolution is controlled by two additional keyword arguments:

ParameterDescription
resolve_crossingsCrossings between contours of different classes — contour (A,B) against contour (A,C) on a face of mesh A. Such a pair needs a third mesh to exist, so the pipeline derives this from the number of operands; the flag is declarative.
resolve_self_crossingsCrossings within one contour class (A,B): a contour with itself, or with another contour of the same pair — e.g. two disjoint components of one mesh cutting the same face.
withinAlso intersect each mesh with itself. Required when a mesh can self-overlap, e.g. meshes concatenated into one input; implies self-crossing resolution. Applies to arrangements and booleans only — intersection_curves does not take it; for a mesh against itself use self_intersection_curves. Default False.

Tolerance

A non-zero tolerance widens the predicates' zero-comparisons by the given world-coordinate distance: features within that distance are classified as coincident, and the five-type partition is unchanged. The band governs both the pairing and the classification — two faces closer than the tolerance are paired and weld even when neither exactly touches the other's plane, and pairs separated by more than the band are rejected. Downstream stages run on exact predicates.

(faces, points), tag_labels, face_labels = tf.mesh_arrangements(
    [mesh0, mesh1], tolerance=1e-6)

A tolerance of 0 is a no-op: the kernel runs exact and the result is invariant.

Each function sets appropriate defaults — see the individual function documentation below and in Cut.

Intersection Curves

Between Two Meshes

mesh0 = tf.Mesh(*tf.read_stl("mesh0.stl"))
mesh1 = tf.Mesh(*tf.read_stl("mesh1.stl"))

paths, points = tf.intersection_curves(mesh0, mesh1)
paths, points = tf.intersection_curves(mesh0, mesh1, mode="primitives")

Default: mode="sos", resolve_crossings=False, resolve_self_crossings=False. With two meshes every contour is of the one class (A,B); crossings among them — e.g. from disjoint components of one mesh — are resolved by resolve_self_crossings or within.

N-Mesh Intersection Curves

Compute all pairwise intersection curves from a list of meshes:

paths, points = tf.intersection_curves([mesh0, mesh1, mesh2])
paths, points = tf.intersection_curves(
    [mesh0, mesh1, mesh2], mode="primitives", resolve_crossings=True)

Default: mode="sos", resolve_crossings=True (for 3+ meshes), resolve_self_crossings=False.

Self-Intersection Curves

Find where a mesh intersects itself:

paths, points = tf.self_intersection_curves(mesh)
paths, points = tf.self_intersection_curves(mesh, mode="primitives")

Default: mode="sos", resolve_crossings=True, resolve_self_crossings=True.

To embed self-intersection curves into mesh topology, use tf.embedded_self_intersection_curves from the Cut module.

With Transformations

import numpy as np

mesh1.transformation = np.eye(4, dtype=np.float32)
mesh1.transformation[:3, 3] = [5, 0, 0]

paths, points = tf.intersection_curves(mesh0, mesh1)

Using Curves

for path_ids in paths:
    curve_points = points[path_ids]
    # Process curve

Isocontours

Extract isocontour curves from scalar fields on meshes.

To cut meshes into regions using isocontours, use tf.isobands from the Cut module.

Single Isocontour

scalar_field = tf.distance(tf.Point(mesh.points), plane)

paths, points = tf.isocontours(mesh, scalar_field, 0.0)

Multiple Isocontours

thresholds = np.array([0.0, 0.5, 1.0], dtype=np.float32)
paths, points = tf.isocontours(mesh, scalar_field, thresholds)
For implementation details, exact arithmetic, and low-level intersection access, see the C++ Intersect documentation.