Intersect
The Intersect module computes geometric intersections between meshes. 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
Curves are returned as (paths, points) tuples where paths is an OffsetBlockedArray of index sequences and points is a numpy array of coordinates.
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, andresolve_self_crossingskeyword arguments — see Intersection Configuration.
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:
| Mode | Description |
|---|---|
"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:
| Parameter | Description |
|---|---|
resolve_crossings | Crossings 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_crossings | Crossings 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. |
within | Also 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 is a statement about the INPUT, not about a predicate, and it is spent entirely on making the input something the exact pipeline can process. Faces whose quantized directions agree are POOLED, and a pool commits one exact plane through original vertices of its own members; every vertex then moves at most the tolerance from where you put it — onto its pool's committed plane where it has one, and otherwise onto a lattice point of the quantized planes its own faces stand on: the meet of three at a corner, a line of two on a crease, its own tangent plane where the surface is smooth. What the pipeline arranges is that moved mesh, EXACTLY: every predicate below the placement runs at zero. Two features closer than the tolerance therefore meet only when the placement puts them on the same lattice point — a weld is identity, not proximity, and one form's rim is never dragged onto another's wall for being near it. Nothing is promised of the output mesh; the tolerance is a licence to move the input, not a bound on the result.
(faces, points), tag_labels, face_labels = tf.mesh_arrangements(
[mesh0, mesh1], tolerance=1e-6)
A tolerance of 0 is the identity: nothing is pooled, nothing moves, no placement table is built, and the result is the exact arrangement of the input as given.
Each function sets appropriate defaults — see the individual function documentation below and in Arrangement.
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="primitives", 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="primitives", 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="primitives", resolve_crossings=True, resolve_self_crossings=True.
tf.polygon_arrangements from the Arrangement 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
