Home Features Desktop App CLI Reference Tutorial Reports Manufacturing Tolerance 3D Analysis Collaboration Integrations Why Plain Text? GitHub

3D Tolerance Analysis with GD&T

Enter your GD&T callouts and let Tessera compute 6-DOF tolerance stackups automatically.

Overview

Tessera's 3D tolerance analysis lets you work with familiar GD&T symbols from your drawings. Enter your position, perpendicularity, runout, and other callouts, and Tessera automatically converts them to a 6-DOF analysis.

The GD&T-First Approach

Most tolerance tools require you to understand torsor theory before specifying tolerances. Tessera works the other way: enter your GD&T as it appears on the drawing, and we handle the math.

What You Get

  • Automatic DOF mapping - GD&T symbols map to the correct degrees of freedom based on geometry
  • Material condition bonuses - MMC/LMC bonus calculations are automatic
  • Datum reference frames - a 3-2-1 DOF analysis informs which degrees of freedom receive derived bounds when no explicit torsor bounds are stored (datum geometry and datum shift are not yet modeled)
  • Validation - Tessera warns if your GD&T changes but torsor bounds are stale

GD&T Symbol Reference

Tessera supports these GD&T symbols. The table shows which degrees of freedom each symbol affects based on your geometry type.

Position and Location

SymbolGD&TGeometryAffects DOFFormula
position cylinder u, v (circular zone) √(u²+v²) ≤ tol / 2
position sphere, point u, v, w ±(tol / 2)
position plane w ±(tol / 2)
concentricity cylinder, sphere u, v (circular zone) ±(tol / 2)
symmetry plane u ±(tol / 2)

Orientation

SymbolGD&TGeometryAffects DOFFormula
perpendicularity cylinder, cone α, β (conical zone) √(α²+β²) ≤ tol / length
perpendicularity plane α, β ±(tol / length)
parallelism cylinder α, β ±(tol / length)
parallelism plane α, β ±(tol / length)
angularity any α, β ±(tol / length)

Form

SymbolGD&TGeometryAffects DOFFormula
flatness plane w, α, β w: ±(tol / 2); tilt: ±(tol / extent), conical
cylindricity cylinder u, v ±(tol / 2)
circularity cylinder, sphere u, v ±(tol / 2)
straightness cylinder, line α, β ±(tol / length)

Runout

SymbolGD&TGeometryAffects DOFFormula
runout cylinder u, v, α, β radial + angular
total_runout cylinder u, v, w, α, β radial + axial + angular

Profile

SymbolGD&TGeometryAffects DOFFormula
profile_line any u, v ±(tol / 2)
profile_surface any plane: w; cylinder: u, v; other: u, v, w ±(tol / 2)

Material Condition Modifiers

ModifierCodeBonus Calculation
MMC (Ⓜ) mmc bonus = departure from MMC toward LMC, clamped to ≥ 0 (a size-nonconforming feature gets no bonus)
LMC (Ⓛ) lmc bonus = departure from LMC toward MMC, clamped to ≥ 0 (a size-nonconforming feature gets no bonus)
RFS rfs No bonus (default)

Quick Start Workflow

Here's the typical workflow for 3D tolerance analysis with GD&T:

1
Create Feature with GD&T

Create a feature and add your GD&T controls directly from the drawing.

bash
tdt feat new --title "Bore" --component CMP@1 --feature-type internal --no-edit

Then edit the feature file to add GD&T:

yaml
title: Bore
feature_type: internal
geometry_class: cylinder
geometry_3d:
  origin: [0.0, 0.0, 0.0]
  axis: [0.0, 0.0, 1.0]
  length: 25.0

dimensions:
  - name: diameter
    nominal: 20.0
    plus_tol: 0.021
    minus_tol: 0.0

# GD&T from drawing
gdt:
  - symbol: position
    value: 0.25
    datum_refs: [A, B]
    material_condition: mmc
  - symbol: perpendicularity
    value: 0.05
    datum_refs: [A]
2
Compute Torsor Bounds

Let Tessera convert your GD&T to torsor bounds automatically.

bash
# Preview the computed bounds
tdt feat compute-bounds FEAT@1

# Compute and save to feature file
tdt feat compute-bounds FEAT@1 --update

# Include MMC bonus (if you know actual size)
tdt feat compute-bounds FEAT@1 --actual-size 20.015 --update
i Feature: Bore (FEAT-01ABC...) Geometry: cylinder (length: 25.0) GD&T Controls: position: 0.25 (MMC) -> u: ±0.125, v: ±0.125 perpendicularity: 0.05 -> α: ±0.002, β: ±0.002 Computed torsor_bounds: u: [-0.125, 0.125] v: [-0.125, 0.125] w: [0, 0] alpha: [-0.002, 0.002] beta: [-0.002, 0.002] gamma: [0, 0]
3
Create Stackup

Add features to a tolerance stackup and run 3D analysis.

bash
# Create stackup
tdt tol new --title "Shaft-Bore Fit" --target-name "Clearance" \
  --target-nominal 0.02 --target-upper 0.05 --target-lower 0.005 --no-edit

# Add contributors
tdt tol add TOL@1 +FEAT@1 ~FEAT@2

# Run 3D analysis
tdt tol analyze TOL@1 --3d
4
Keep Bounds Current

Tessera validates that your torsor bounds match your GD&T.

bash
# Check for stale bounds
tdt validate

# Auto-fix stale bounds
tdt validate --fix
Tip: Validate After Changes

After modifying GD&T values, run tdt validate to ensure your torsor bounds are current. Use --fix to automatically update stale bounds.

Feature Setup

Features need geometry information for 3D analysis. This tells Tessera what type of geometry and where it is in your assembly.

Required Fields

FieldDescriptionExample
geometry_class Type of geometry cylinder, plane, sphere, cone, point, line
geometry_3d.origin Position in assembly coordinates [0.0, 0.0, 50.0]
geometry_3d.axis Direction vector (normalized) [0.0, 0.0, 1.0]
geometry_3d.length Feature length (for angular tolerances) 25.0
geometry_3d.length_ref Optional: reference another feature's dimension "FEAT-01ABC:depth"
Tip: Reference Dimensions

Use length_ref to link a feature's length to another feature's dimension. This ensures values stay in sync. Format: "FEATURE_ID:dimension_name".

CLI command: tdt feat set-length FEAT@2 --from FEAT@1:depth sets the length and reference automatically.

Run tdt validate to check for stale values, or tdt validate --fix to update them.

Geometry Examples

Cylinder (Bore or Shaft)

yaml
geometry_class: cylinder
geometry_3d:
  origin: [0.0, 0.0, 0.0]    # Center at one end
  axis: [0.0, 0.0, 1.0]      # Along Z axis
  length: 25.0               # Depth of bore

Plane (Face or Datum Surface)

yaml
geometry_class: plane
geometry_3d:
  origin: [0.0, 0.0, 0.0]    # Point on surface
  axis: [0.0, 0.0, 1.0]      # Surface normal

Sphere (Ball or Locating Feature)

yaml
geometry_class: sphere
geometry_3d:
  origin: [50.0, 25.0, 10.0] # Center point
  axis: [0.0, 0.0, 1.0]      # Reference direction

Coordinate System

Use a consistent coordinate system for all features. A common convention:

Z (up) | | | +--------- Y / / X Right-hand rule: X x Y = Z

Datums

Add datum_label to features that serve as datums:

yaml
title: Mounting Face
geometry_class: plane
# ... geometry ...

# This feature is datum A
datum_label: A

Tessera applies the ASME Y14.5 3-2-1 rule automatically:

  • Primary datum (A) - Constrains 3 DOF
  • Secondary datum (B) - Constrains 2 additional DOF
  • Tertiary datum (C) - Constrains final 1 DOF

When you specify datum_refs: [A, B] in your GD&T, Tessera only applies tolerances to DOFs not already constrained by those datums.

Running Analysis

bash
tdt tol analyze TOL@1 --3d

Example Output

i Found datum features: A, B Analyzing stackup TOL@1 with 4 contributors... Analysis complete Target: Clearance = 0.02 (LSL: 0.005, USL: 0.05) Worst-Case Analysis: Range: -0.01 to 0.04 Result: marginal RSS (Statistical) Analysis: Mean: 0.015 ±3σ: 0.012 Capability: Cp=1.87, Cpk=1.46 Yield: 99.99% 6-DOF Torsor Results: Translations (mm): u: WC [-0.018, 0.018] RSS ±3σ=0.0102 v: WC [-0.018, 0.018] RSS ±3σ=0.0102 w: WC [0, 0] Rotations (mrad): α: WC [-0.50, 0.50] RSS ±3σ=0.28 β: WC [-0.50, 0.50] RSS ±3σ=0.28 γ: WC [0, 0] Functional Deviation (projected onto [1,0,0]): Worst Case: 0.018 RSS 3σ: 0.0102

How Bounds Are Used

The 3D analysis uses torsor bounds to determine geometric deviation for each contributor:

  • GD&T torsor_bounds - If a feature has torsor_bounds (computed from GD&T via compute-bounds), these are used directly
  • Derived bounds - If no torsor_bounds exist, bounds are derived from the contributor's dimensional tolerance

The analysis output shows which source was used:

Using GD&T torsor_bounds: Bore, Shaft Journal Using derived bounds (no torsor_bounds): Spacer Thickness
Best Practice

For accurate 3D analysis, always define GD&T controls on your features and run tdt feat compute-bounds --update to generate proper torsor bounds. This ensures your analysis uses the actual geometric tolerances from your drawing rather than approximations from dimensional tolerance.

Analysis Options

FlagDescription
--3dEnable 6-DOF SDT analysis
--measurement-point "x,y,z"Where the result is evaluated (put it at the functional gap). Persisted on the stackup; defaults to the assembly origin
--seed NReproducible Monte Carlo — same seed, same chain, identical results (seed is recorded in the results for audit trails)
--visualizeShow ASCII chain diagram
--iterations NMonte Carlo iterations (default: 10000)
--no-gdt1D analysis only: exclude GD&T position tolerances (3D always uses the full GD&T model)

Understanding Results

  • WC [min, max] - Worst-case deviation range
  • RSS ±3σ - Statistical 3-sigma spread
  • Cp/Cpk - Process capability indices
  • Zero DOFs - Fully constrained by geometry or datums

Worked Example: Rotated Bore + Face

A complete example you can follow end to end — and check by hand. A manifold block has a dowel-pin bore drilled along the X axis and a locating face on top. We want the deviation at the bore's location, normal to the face (Z).

1. The features

The bore: Ø6 H7, true-position Ø0.2 (M) to |A|B|, axis along X at (30, 0, 10):

yaml — FEAT@1 (excerpt)
geometry_class: cylinder
geometry_3d:
  origin: [30.0, 0.0, 10.0]
  axis: [1.0, 0.0, 0.0]      # bore drilled along X
  length: 12.0
dimensions:
  - name: bore_diameter
    nominal: 6.0
    plus_tol: 0.012          # H7
    minus_tol: 0.0
gdt:
  - symbol: position
    value: 0.2
    units: mm
    datum_refs: ["A", "B"]
    material_condition: mmc

The locating face: plane, normal Z at height 20, flatness 0.05 over its 40 mm extent:

yaml — FEAT@2 (excerpt)
geometry_class: plane
geometry_3d:
  origin: [0.0, 0.0, 20.0]
  axis: [0.0, 0.0, 1.0]
  length: 40.0               # extent, used for the tilt bound
gdt:
  - symbol: flatness
    value: 0.05
    units: mm
    datum_refs: []           # flatness is a form control — no datum needed

2. Compute bounds, build the stackup, analyze

bash
tdt feat compute-bounds FEAT@1 --actual-size 6.006 --update   # MMC bonus from measured size
tdt feat compute-bounds FEAT@2 --update
tdt tol new -t "Pin-to-face gap" --target-name gap --target-nominal 10 --target-upper 10.3 --target-lower 9.7 --no-edit
tdt tol add TOL@1 +FEAT@1 ~FEAT@2
tdt tol analyze TOL@1 --3d --seed 777 --measurement-point "30,0,10"

(Set functional_direction: [0, 0, 1] on the stackup — we care about the Z gap.)

3. What comes out, and why

3D SDT Analysis (6-DOF Torsor): Translations (mm): u: WC [-0.013, 0.013] ← face tilt × 10 mm Z lever only v: WC [-0.115, 0.115] ← bore radial (0.103) + face tilt × 10 mm w: WC [-0.165, 0.165] ← see the arithmetic below Rotations (mrad): α, β: WC [-1.250, 1.250] ← flatness tilt: 0.05 / 40 = 1.25 mrad Functional Deviation (projected onto [0,0,1]): Worst Case: PASS (range: -0.165 to 0.165) Capability: Cp=2.67, Cpk=2.67, Yield=100.00%

Every number is checkable by hand:

  • Bore radial zone: ±0.103. Ø0.2 position zone → radius 0.1, plus MMC bonus (6.006 − 6.000 = 0.006 diameter) → radius 0.103. Because the bore points along X, its radial zone lands in the global (Y, Z) plane — the rotated frame puts the tolerance where the physics puts it. Nothing deviates along the bore's own axis (u ≈ 0 from this feature).
  • Face flatness: ±0.025 translation, ±1.25 mrad tilt. The substitute plane can sit anywhere in the 0.05 zone (±t/2) and tilt up to t/extent = 0.05/40 = 1.25 mrad about any in-plane axis (a conical, coupled zone).
  • Lever arm. The face sits at (0, 0, 20); the measurement point is (30, 0, 10), so d = (30, 0, −10). The tilt contributes |d| × tilt to translation at the measurement point: 30 mm × 1.25 mrad = 0.0375 mm to w, and 10 mm × 1.25 mrad = 0.0125 mm to u and v.
  • Total w worst case: 0.103 (bore, rotated into Z) + 0.025 (flatness translation) + 0.0375 (tilt × lever arm) = 0.1655 ✓
Reading the result

The functional deviation is a deviation from nominal: WC ±0.165 against a ±0.3 spec band → PASS with margin. Re-run with --seed 777 and you get bit-identical Monte Carlo numbers — the seed is stored in the results for audit trails. Add mean_shift_k: 1.5 to the stackup and Cpk drops from 2.67 to 2.17: the Bender shift models long-term process drift toward the nearest limit.

Theory Deep Dive

This section explains the underlying math for those who want to understand how Tessera works internally.

Small Displacement Torsor (SDT)

A torsor represents the small deviation of a feature from its nominal position using 6 parameters:

ComponentSymbolDescription
uuTranslation along local X
vvTranslation along local Y
wwTranslation along local Z
alphaαRotation about local X
betaβRotation about local Y
gammaγRotation about local Z

Geometry Class DOF Constraints

Different geometry types constrain different degrees of freedom:

GeometryConstrainedFree
planew, α, βu, v, γ
cylinderu, v, α, βw, γ
sphereu, v, wα, β, γ
coneu, v, w, α, βγ
lineu, vw, α, β, γ
pointu, v, wα, β, γ

Jacobian Propagation

Tessera uses Jacobian matrices to propagate deviations through the tolerance chain. Each feature's torsor lives in its local frame: local w lies along the feature's geometry_3d.axis, and the frame is the minimal (smallest-angle) rotation R taking the assembly +Z axis onto that axis — a feature pointing along +Z has exactly the assembly frame. The deviation contributed at the measurement point P is:

δP = R·δT + (R·δR) × (P − p) (translation at P) δΩ = R·δR (rotation) | R −[d]×·R | J = | | with d = P − p | 0 R | where: δT = [u, v, w] (translation deviation, local frame) δR = [α, β, γ] (rotation deviation, local frame) p = feature position (geometry_3d.origin) P = measurement point (stackup measurement_point; default origin)

Because of the lever arm d = P − p, a small tilt at a feature far from the measurement point produces a large translation there — put measurement_point where the functional gap physically is, or the tilt contributions will be attributed to the wrong place.

Circular vs Square Zones

A Ø position zone is a circle: the axis deviation satisfies √(u² + v²) ≤ t/2, and the corner of the bounding square (u = v = t/2 simultaneously) is not a legal part. Tessera tracks this with uv_circular on the stored bounds:

  • Worst case uses the exact extreme of a circular zone: ρ·√(jᵤ² + jᵥ²) instead of the square's ρ·(|jᵤ| + |jᵥ|) — up to √2 tighter with no loss of conservatism.
  • Monte Carlo samples uniform/triangular pairs inside the disc (a normal pair is rotationally symmetric already).
  • The same treatment applies to conical orientation zones via ab_circular: total axis tilt √(α² + β²) ≤ t/L.
  • When a circular and a square control merge on the same DOF pair, the square (conservative) interpretation wins.

GD&T to Torsor Mapping

The compute-bounds command applies these rules:

  1. Parse GD&T controls from feature
  2. For each control, determine affected DOFs based on geometry class
  3. Compute bounds: translation tolerances → ±(tol/2), angular tolerances → ±(tol/length)
  4. Apply material condition bonus if actual size provided
  5. Merge multiple controls (tightest bound wins for same DOF)

Model Scope & Limitations

The 3D engine models rotated feature frames, a configurable measurement point, circular/conical tolerance zones, chain direction, and Bender mean shift natively. What remains out of scope:

  • Datum modeling is partial. The 3-2-1 analysis selects which DOFs receive derived bounds (and only from the first GD&T control); datum feature geometry, datum precedence effects, and MMC datum shift (bonus from datum features of size) are not modeled. tdt validate warns when a datum-dependent control (position, orientation, runout) has no datum_refs.
  • include_gdt is a 1D-only switch. The 3D path always uses the full GD&T model — that is its purpose — so the flag has no effect there.
  • Nominal chain closure is assumed, not checked. The 3D result is a deviation from nominal; verify your nominal dimension chain closes with the 1D analysis.
  • Staleness detection covers stackup-level 3D inputs (functional_direction and measurement_point are hashed) but not linked feature files — re-run tdt tol analyze --3d after changing a feature's geometry_3d or torsor_bounds.
  • Small-displacement assumption. Like all SDT methods, rotations are linearized (sin θ ≈ θ); fine for tolerance-scale deviations, wrong for mechanisms.

Reference

CLI Commands

CommandDescription
tdt feat compute-bounds FEAT@1Show computed torsor bounds from GD&T
tdt feat compute-bounds FEAT@1 --updateCompute and save to file
tdt feat compute-bounds FEAT@1 --actual-size 20.01Include MMC/LMC bonus
tdt tol analyze TOL@1 --3dRun 3D SDT analysis
tdt tol analyze TOL@1 --3d --visualizeWith chain visualization
tdt validateCheck for stale torsor bounds
tdt validate --fixAuto-fix stale bounds

GD&T Field Format

yaml
gdt:
  - symbol: position           # GD&T symbol name
    value: 0.25                # Tolerance value
    datum_refs: [A, B, C]      # Datum references (optional)
    material_condition: mmc    # mmc, lmc, or rfs (default)

Supported Symbols

position, concentricity, symmetry, perpendicularity, parallelism, angularity, flatness, cylindricity, circularity, straightness, runout, total_runout, profile_line, profile_surface

Further Reading