How to Create Assemblies with build123d Joints in the Text-to-CAD Library
The Text-to-CAD library wraps native build123d joint functionality through the AssemblyHelper class, allowing you to define datum frames, connect parts with rigid, revolute, and linear joints, and export complete assemblies to STEP format without directly manipulating build123d APIs.
The earthtojake/text-to-cad repository provides a high-level Python interface for programmatic CAD assembly creation. By leveraging the AssemblyHelper class in viewer/packages/cadpy/src/cadpy/assembly.py, engineers can create complex mechanical assemblies using build123d joints while abstracting away low-level geometric constraints.
Understanding the AssemblyHelper Architecture
The AssemblyHelper class serves as the central orchestrator for assembly creation. It manages part registration, joint definition, and relationship mapping through a declarative API that internally constructs native build123d joint objects.
Core Joint Frame Methods
To establish connection points on individual parts, the helper provides specialized frame methods that return MateTarget objects. These include rigid_frame(), revolute_frame(), linear_frame(), cylindrical_frame(), and ball_frame(), each creating the appropriate build123d joint type at a specified location and orientation.
Connection Utilities
Once frames are defined, methods like connect(), face_to_face(), coaxial(), revolute(), and linear() establish relationships between fixed and moving targets. These utilities automatically invoke _normalize_target to process (part, frame_name) tuples and _joint_for_target to retrieve underlying build123d joint instances from the part's joints mapping, storing the result as a MateRelation.
Step-by-Step: Creating Your First Assembly
Begin by importing the necessary modules and instantiating AssemblyHelper with a unique assembly name.
import build123d
from cadpy.assembly import AssemblyHelper, target
# Initialize the assembly container
assy = AssemblyHelper("my_assembly")
# Add primitive shapes as parts
part_a = assy.add(build123d.Box(20, 10, 5).wrapped, "base")
part_b = assy.add(build123d.Cylinder(5, 30).wrapped, "shaft")
Next, define datum frames on each part where mechanical connections will occur.
# Create a rigid datum at the center of the base
rigid_a = assy.rigid_frame(part_a, "origin", build123d.Location((0, 0, 0)))
# Create a revolute datum aligned with the cylinder's central axis
revolute_b = assy.revolute_frame(
part_b,
"axis",
axis=build123d.Location((0, 0, 1)),
axis_offset=build123d.Location((0, 0, 0))
)
Finally, connect the frames using the appropriate joint type and positional offset.
# Rigidly attach the shaft to the base with a 5mm vertical offset
assy.connect(
fixed=rigid_a,
moving=revolute_b,
relation="rigid",
offset=build123d.Location((0, 0, 5))
)
Advanced Joint Types and Relationships
Beyond basic rigid connections, the library supports sophisticated mechanical relationships through specialized mating methods.
Rigid and Revolute Connections
Use assy.connect() with relation="rigid" for fixed attachments where no relative motion occurs. For rotational degrees of freedom, first declare a revolute_frame() on the part to establish the axis of rotation, then use assy.revolute() to constrain the motion between two mating frames.
Linear and Coaxial Mating
For prismatic sliding motion, linear_frame() creates the translational axis on a part, while assy.linear() sets the specific travel position between two frames. The coaxial() convenience method automatically aligns cylindrical features, making it ideal for shaft-and-bearing assemblies without manual axis alignment.
# Define sliding axes on both parts
linear_a = assy.linear_frame(part_a, "slide_a", axis=build123d.Location((1, 0, 0)))
linear_b = assy.linear_frame(part_b, "slide_b", axis=build123d.Location((1, 0, 0)))
# Connect with 10mm of travel
assy.linear(fixed=linear_a, moving=linear_b, position=10.0)
# Or use coaxial alignment for cylindrical features
assy.coaxial(fixed=target(part_a, "axis"), moving=target(part_b, "axis"))
Exporting Assemblies to STEP
The build() method aggregates all child shapes into a build123d.Compound. When no explicit children are supplied, the helper automatically injects assembly_mates metadata—serialized via the private _mate_endpoint_payload utility—into the resulting geometry. This metadata captures each joint's position, orientation, and axis data.
Use export_build123d_step_scene() from viewer/packages/cadpy/src/cadpy/step_export.py to generate the final STEP file containing the assembly structure.
# Generate the compound with embedded joint metadata
final_assembly = assy.build()
# Export to STEP format
from cadpy.step_export import export_build123d_step_scene
export_build123d_step_scene(final_assembly, "my_assembly.step")
The resulting STEP file contains an assemblyMates section that lists each defined joint, its type, and full location data—ready for downstream tools such as CAD viewers or robot simulation pipelines.
Summary
- The
AssemblyHelperclass inviewer/packages/cadpy/src/cadpy/assembly.pyprovides a high-level wrapper around native build123d joints. - Frame declaration methods like
rigid_frame()andrevolute_frame()create local datum references that returnMateTargetobjects. - Connection utilities establish mechanical relationships without requiring direct build123d API calls.
- The internal
_joint_for_targetand_mate_endpoint_payloadmethods handle joint retrieval and serialization. - Assemblies export to STEP format with embedded joint metadata via
export_build123d_step_scene().
Frequently Asked Questions
What is the AssemblyHelper class in text-to-cad?
The AssemblyHelper class is the primary interface in viewer/packages/cadpy/src/cadpy/assembly.py that abstracts build123d's native joint system. It provides methods to label parts via label_shape, define joint frames, connect components using connect() or face_to_face(), and export complete assemblies, eliminating the need to manually manage build123d's lower-level joint APIs.
How does text-to-cad handle build123d joint serialization?
The library uses the private utility _mate_endpoint_payload to serialize each joint's position, orientation, and axis data into a structured format. When build() is called, this metadata populates the assembly_mates attribute of the resulting Compound, which export_build123d_step_scene() then embeds into the STEP file's assemblyMates section for external compatibility.
Can I use raw build123d joints with AssemblyHelper?
While the helper is designed to abstract build123d joints, you can access the underlying joint objects through the joints dictionary stored on individual parts. The _joint_for_target method retrieves these native objects when establishing connections, ensuring compatibility with the broader build123d ecosystem while maintaining the helper's simplified declarative workflow.
Where are assembly definitions stored in the exported files?
Joint definitions and mate relationships are stored in the assemblyMates metadata section of exported STEP files. This section lists each joint type, its associated parts, and full transformation data including position vectors and rotation matrices, making the assemblies compatible with mechanical CAD viewers and robotic simulation pipelines that parse STEP assembly structures.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →