Skip to content

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:

Create shapes → Combine with booleans → Modify with operations → Debug with snapshots
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