How to Create Named Mating Datums and Positioning in Assemblies with Text-to-CAD

Text-to-CAD implements assembly mating through the AssemblyHelper class in packages/cadpy/src/cadpy/assembly.py, which provides a three-step workflow to define named datums on parts, create kinematic joint frames, and connect them to generate export-ready STEP payloads.

The earthtojake/text-to-cad repository provides a Python API for programmatically defining mechanical assemblies with fully-typed mating relationships. Built on top of build123d, the AssemblyHelper class bridges geometric modeling with STEP-compatible assembly metadata, enabling precise positioning through named reference frames and joint definitions.

The Three-Stage Assembly Workflow

Creating named mating datums and positioning in assemblies follows a deterministic pipeline implemented in packages/cadpy/src/cadpy/assembly.py. The workflow progresses from reference frame definition to kinematic connection, culminating in structured export data.

1. Define Named Datums with datum()

Use the datum() method (lines 32-39) to assign STEP-friendly labels to specific locations on part geometries. This method wraps label_shape and utilizes label_text() to generate compact, unique identifiers like mount:center or base:front_left that serve as standardized anchor points during assembly operations.

from cadpy.assembly import AssemblyHelper
import build123d as bd

asm = AssemblyHelper("robot_arm")
base_plate = bd.Box(100, 100, 10)

asm.add(base_plate, "base_plate")
asm.datum(base_plate, "mount", "center")  # Creates label "mount:center"

2. Create Joint Frames

Joint frames define the kinematic relationship between mating parts. AssemblyHelper provides specialized factory methods—rigid_frame(), revolute_frame(), linear_frame(), cylindrical_frame(), and ball_frame()—that delegate to internal builders including add_rigid_frame, add_axis_frame, and add_joint_frame (lines 61-67 and 70-78).

link_body = bd.Cylinder(5, 50)
asm.add(link_body, "link_body")

# Create rigid frame at specific location

link_tip = asm.rigid_frame(link_body, "link_tip", bd.Location((0, 0, 0)))

3. Connect Frames with connect()

The connect() method (lines 71-87) establishes MateRelation records by normalizing targets and creating native build123d joints. It accepts MateTarget objects or tuples specifying the part and datum frame, recording the relationship for downstream export pipelines.

asm.connect(
    fixed=(base_plate, "mount:center"),
    moving=link_tip,
    relation="rigid",
    label="base_to_link"
)

Working with MateTarget and MateRelation

MateTarget is a lightweight wrapper exposing part and frame attributes that reference specific datums within the assembly hierarchy. MateRelation stores the complete connection metadata—including label, relation type, fixed and moving targets, and kinematic parameters—for consumption by STEP/URDF exporters.

During export, the helper aggregates all relations via assembly_mate_payload() (lines 60-89) into a JSON-compatible structure. This payload is attached to the final STEP scene through _attach_assembly_mates in packages/cadpy/src/cadpy/step_export.py (line 48), ensuring mating data persists in the exported CAD file.

Offsetting Frames for Precise Positioning

Use offset_target() (lines 92-108) to create displaced reference frames relative to existing datums. This method accepts an existing part and datum label along with an offset vector, returning a new MateTarget without modifying the base geometry—essential for defining tool clearances, standoffs, or accommodation features.


# Create frame 5mm above the center datum

offset_mount = asm.offset_target(
    base_plate, 
    "mount:center", 
    offset=(0, 0, 5)
)

Complete Assembly Implementation

The following implementation demonstrates the full pipeline from datum creation to mate relation export:

from cadpy.assembly import AssemblyHelper
import build123d as bd

# Initialize assembly helper

asm = AssemblyHelper("robot_arm")

# Define base with named datum

base = bd.Box(100, 100, 10)
asm.add(base, "base_plate")
asm.datum(base, "mount", "center")

# Define link with rigid frame

link = bd.Cylinder(5, 50)
asm.add(link, "link_body")
link_frame = asm.rigid_frame(link, "link_tip", bd.Location((0, 0, 0)))

# Create rigid connection

asm.connect(
    fixed=(base, "mount:center"),
    moving=link_frame,
    relation="rigid",
    label="base_to_link"
)

# Build final assembly (includes MateRelation payload)

assembly = asm.build()

The resulting assembly compound contains embedded mate metadata. When exported through the STEP pipeline, the payload includes structured entries like:

{
  "id": "m1",
  "label": "m1",
  "sourceLabel": "base_to_link",
  "type": "rigid",
  "relation": "rigid",
  "fixed": "mount:center",
  "moving": "link_tip",
  "parameters": {}
}

Summary

  • Named datums are created via AssemblyHelper.datum() in packages/cadpy/src/cadpy/assembly.py (lines 32-39), utilizing label_shape and label_text() to generate STEP-compatible identifiers for part reference frames.
  • Joint frames support multiple kinematic types—rigid, revolute, linear, cylindrical, and ball—through factory methods delegating to add_rigid_frame, add_axis_frame, and add_joint_frame (lines 61-78).
  • Frame connections are recorded as MateRelation objects via connect() (lines 71-87), storing fixed/moving MateTarget references, relationship types, and parameters.
  • Export pipeline aggregates mates through assembly_mate_payload() (lines 60-89) and attaches them to STEP scenes via _attach_assembly_mates in packages/cadpy/src/cadpy/step_export.py (line 48).
  • Position offsets are achieved using offset_target() (lines 92-108) to create derived reference frames for clearance and tooling requirements.

Frequently Asked Questions

How does Text-to-CAD generate STEP-compatible labels for assembly datums?

Text-to-CAD generates labels through the label_text() utility, which creates compact, STEP-safe identifiers like part_name:datum_name. These are assigned to shapes via label_shape within the datum() method (lines 32-39 of packages/cadpy/src/cadpy/assembly.py), ensuring reference frames remain unique and readable in exported STEP files.

What types of joint frames does AssemblyHelper support?

AssemblyHelper supports five kinematic frame types: rigid, revolute, linear, cylindrical, and ball. Each type has a corresponding factory method that constructs the appropriate build123d joint geometry and delegates to internal methods like add_rigid_frame or add_axis_frame (lines 61-78).

How are assembly connections stored before export?

Connections are stored as MateRelation objects containing the relationship label, kinematic type, fixed and moving MateTarget references, and optional parameters. These records are collected by assembly_mate_payload() (lines 60-89) and attached to the export artifact via _attach_assembly_mates in packages/cadpy/src/cadpy/step_export.py (line 48).

Can I create offset datum frames for clearance requirements?

Yes. Use offset_target() (lines 92-108 in packages/cadpy/src/cadpy/assembly.py) to generate new reference frames displaced from existing datums. This method accepts an offset vector and creates a derived MateTarget without modifying the original part geometry, enabling precise positioning for clearance zones or tooling attachments.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →