Key Concepts¶
llmcad has a small API surface by design. Understanding these core concepts is all you need to build complex 3D models.
The modeling workflow¶
Every llmcad model follows the same pattern:
from llmcad import Box, Cylinder, Rect, extrude, fillet, snapshot
# 1. Create shapes
plate = Box(100, 60, 10)
peg = Cylinder(8, 20)
# 2. Combine with booleans
plate = plate + peg # union
# 3. Modify with operations
plate = fillet(plate.top.edges, radius=2)
# 4. Debug
snapshot(plate, "my_model")
Bodies¶
A Body is the core object in llmcad. It wraps a 3D solid shape and carries:
- Named faces ---
body.top,body.front,body.faces["my_face"] - Named edges ---
body.edges,face.edges,face.left_edge - Color ---
body.color = "steel" - Position ---
body.position(center of bounding box)
Bodies are immutable --- every boolean operation returns a new Body:
plate = Box(100, 60, 10)
boss = extrude(Rect(30, 30).place_on(plate.top), amount=20)
# This creates a NEW body, plate is unchanged
result = plate + boss
Named faces¶
Every body has automatically named faces based on their orientation:
| Face | Normal direction | Shortcut |
|---|---|---|
top |
+Z | body.top |
bottom |
-Z | body.bottom |
front |
-Y | body.front |
back |
+Y | body.back |
right |
+X | body.right |
left |
-X | body.left |
Cylinders have top, bottom, and wall. Spheres have surface.
When you extrude a sketch, the start and end cap faces are named _start and _end:
boss = extrude(Rect(30, 30).place_on(plate.top), amount=20, name="boss")
plate = plate + boss
# After union, the end cap is accessible as:
plate.faces["_end"] # the top of the boss
Face-local coordinate systems¶
This is the key idea that makes llmcad LLM-friendly.
Each face has its own local 2D coordinate system:
- x_dir --- "rightward" on the face
- y_dir --- "upward" on the face
- normal --- outward perpendicular (the face's Z)
When you call position.offset(dx=10, dy=5), the offset is in face-local coordinates, not global XYZ. This means LLMs don't need to reason about 3D rotations --- just "move right" and "move up" on a face.
# Place a hole 15mm to the right of center on the top face
pos = plate.top.center.offset(dx=15)
hole = extrude(Circle(6).place_on(plate.top, at=pos), through=True)
Sketches¶
Sketches are 2D shapes that live on the XY plane until placed on a face:
rect = Rect(30, 20) # 30mm x 20mm rectangle
circ = Circle(10) # 10mm diameter circle (NOT radius)
elip = Ellipse(40, 20) # 40mm x 20mm ellipse
tri = Polygon([(0,0), (40,0), (20,30)]) # triangle
label = Text("HELLO", 12) # text as geometry
For complex profiles, use the turtle-style Sketch builder:
s = Sketch()
s.start(0, 0)
s.line_to(80, 0, name="bottom")
s.line_to(80, 60)
s.arc_to(0, 60, radius=10)
s.close(name="left")
Sketches are placed on faces with .place_on():
placed = Rect(30, 20).place_on(plate.top) # at face center
placed = Rect(30, 20).place_on(plate.top, at=pos) # at specific position
Booleans¶
Combine bodies with Python operators:
| Operator | Operation | Result |
|---|---|---|
a + b |
Union (fuse) | Merged solid |
a - b |
Cut (subtract) | b removed from a |
a & b |
Intersect | Only overlapping volume |
Face names survive boolean operations --- llmcad automatically transfers them to the new body.
Operations¶
| Function | What it does |
|---|---|
extrude(sketch, amount=20) |
Push a 2D sketch into 3D |
revolve(sketch, angle=360) |
Revolve a sketch around an axis |
loft(sketches, heights) |
Smooth transition between sketches |
sweep(path, cross_section) |
Sweep a profile along a path |
fillet(edges, radius=3) |
Round edges |
chamfer(edges, size=2) |
Bevel edges |
shell(body, thickness=2) |
Hollow out a body |
split(body, plane) |
Split body with a plane |
mirror(body, plane) |
Mirror body about a plane |
Debugging¶
snapshot(body, "name") # Save multi-view PNG (front, right, top, iso)
show(body) # Open in OCP CAD Viewer (VSCode)
measure(pos_a, pos_b) # Print distance between two positions
Assembly¶
Position parts on faces and combine them:
boss = Cylinder(20, height=30)
boss = place(boss, on=base.top, at=base.top.center)
base = base + boss
For multi-part assemblies, use the Assembly class:
asm = Assembly(name="enclosure")
asm.add(base, name="base")
asm.add(lid, name="lid")
result = asm.build()
Summary¶
| Concept | Description |
|---|---|
Body |
3D solid with named faces and edges |
FaceRef |
Named face with local coordinate system |
EdgeRef |
Named edge with midpoint and length |
Position |
3D point with face-local offsets |
Rect, Circle, ... |
2D sketch primitives |
Sketch |
Turtle-style sketch builder |
extrude, revolve, ... |
2D → 3D operations |
fillet, chamfer, shell |
Body modification |
split, mirror |
Body transformation |
place, Assembly |
Part positioning and assembly |
+, -, & |
Boolean combination |
snapshot |
Visual debugging |