Can AI Write CAD? Testing LLM-Generated 3D Models for Manufacturability
A student’s test plan for checking whether LLMs can write usable parametric CAD: five parts, fixed pass/fail rules, and manufacturability checks.

Signup Write New Story Can AI Write CAD? Testing LLM-Generated 3D Models for Manufacturability by Melody Cole by Melody Cole | @ melodycole Mechanical Engineering student at Carnegie Mellon University | Exploring engineering, technology, design, and innovation.
Mechanical Engineering student at Carnegie Mellon University | Exploring engineering, technology, design, and innovation.
I am a mechanical engineering student, and like most students I now see AI tools everywhere. They explain thermodynamics, debug my Python, and summarize papers. So one question kept bothering me: if an AI can write code, can it also write a mechanical design?
Code and CAD feel closely related. Tools like CadQuery and OpenSCAD let you describe a 3D part as a script, so in theory an LLM that writes the script can “design” a part from a text description.
But there is a gap between a model that runs and a part that works. A script can execute without errors and still produce a bracket with 0.3 mm walls, holes that overlap the edge, or a gear that cannot mesh with anything. In engineering, “it ran” is not the same as “it is correct.” This article is my attempt, as a student, to define how to measure that gap honestly.
This is Part 1: the method. I am publishing the plan, the rules, and a verified reference script before the results, so that nobody (including me) can bend the criteria to fit the numbers.
To judge AI-generated CAD, it helps to know what CAD software actually stores. Three ideas matter here.
Boundary representation (B-rep). Most mechanical CAD systems describe a solid by its boundary: faces, edges, and vertices, plus the topology that says how they connect. This is why you can select a face and add a fillet. A classic reference for how solids are represented and built up with operations such as union, cut, and intersect is Martti Mäntylä, An Introduction to Solid Modeling (Computer Science Press, 1988).
Constructive solid geometry (CSG). Here a shape is built as a tree of Boolean operations on primitives such as boxes, cylinders, and spheres. OpenSCAD follows this style (OpenSCAD documentation. It is intuitive and very scriptable, but it is mostly used to produce meshes such as STL files, which do not carry the exact faces and edges that B-rep CAD systems use for downstream engineering work.
Curved surfaces in CAD are commonly described with NURBS (Non-Uniform Rational B-Splines). The standard reference is Les Piegl and Wayne Tiller, The NURBS Book, 2nd ed. (Springer, 1997). My understanding is that this is part of why operations like fillets and shells can fail on complex geometry: the kernel has to build new surfaces that stay valid and watertight.
For a broader view of the mathematics behind curves, surfaces, and solids, Michael E. Mortenson, Geometric Modeling, 3rd ed. (Industrial Press, 2006) describes and compares the important methods.
The word parametric matters a lot in this test. A parametric model is driven by named values (length, thickness, hole diameter), so changing one value updates the whole part correctly. The real skill in CAD is not drawing shapes. It is capturing design intent: which dimensions are free, which are constrained, and what must stay true when something changes. A model with hard-coded numbers scattered through the code looks like CAD but behaves like a dead drawing. I treat this as a key test.
I am using CadQuery, a Python module for building parametric 3D CAD models that is based on the OpenCASCADE kernel and can export STEP files; shape objects expose checks such as isValid() and BoundingBox() (CadQuery documentation, I chose code-based CAD for one practical reason: it makes the test reproducible and checkable. I can run the same script on any machine, measure the result with code, and keep everything in version control.
Below is the reference part, an L-bracket with four mounting holes. It shows what “design intent in code” looks like: every dimension is a named parameter, the hole layout is derived from those parameters, and asserts stop the script if the parameters conflict.
import math import cadquery as cq # ---- Parameters (all in millimetres) ---- length = 80.0 # base length along X width = 40.0 # bracket width along Y thickness = 4.0 # base and wall thickness height = 50.0 # overall height along Z hole_dia = 6.5 # clearance hole for an M6 bolt hole_inset = 10.0 # hole centre to the free end and to each side edge hole_pitch_x = 30.0 # spacing between the two hole columns along X # ---- Hole layout, derived from the parameters ---- x_far = length - hole_inset # column nearest the free end x_near = x_far - hole_pitch_x # second column, toward the wall y_edge = width / 2 - hole_inset # two rows at +/- y_edge hole_pts = [(x_near, -y_edge), (x_near, y_edge), (x_far, -y_edge), (x_far, y_edge)] # ---- Design-intent checks: fail early if parameters conflict ---- r = hole_dia / 2 assert x_near - r > thickness, "holes would hit the vertical wall" assert y_edge + r < width / 2, "holes would break through the side edge" assert x_far + r < length, "holes would break through the free end" # ---- L-shaped profile in the XZ plane, extruded symmetrically across Y ---- bracket = ( cq.Workplane("XZ").polyline([ (0, 0), (length, 0), (length, thickness), (thickness, thickness), (thickness, height), (0, height), ]).close().extrude(width / 2, both=True) ) # ---- Cut the mounting holes through the base ---- cutter = ( cq.Workplane("XY").workplane(offset=-1).pushPoints(hole_pts).circle(r).extrude(thickness + 2) ) bracket = bracket.cut(cutter) # ---- Validity checks against a hand calculation ---- solid = bracket.val() profile_area = length * thickness + (height - thickness) * thickness expected_volume = profile_area * width - len(hole_pts) * math.pi * r**2 * thickness bb = solid.BoundingBox() print("Valid solid:", solid.isValid()) print("Solids:", len(bracket.solids().vals())) print("Volume (mm^3):", round(solid.Volume(), 1), "expected:", round(expected_volume, 1)) print("Bounding box (mm):", round(bb.xlen, 1), round(bb.ylen, 1), round(bb.zlen, 1)) assert solid.isValid() assert abs(solid.Volume() - expected_volume) < 1.0 cq.exporters.export(bracket, "bracket.step") cq.exporters.export(bracket, "bracket.stl")
The hand calculation is what makes the checks meaningful. The L-profile area is 80 × 4 + 46 × 4 = 504 mm², and extruding it across the 40 mm width gives 20,160 mm³. The four holes (6.5 mm diameter, 4 mm deep) remove about 531 mm³. So when the script runs correctly it should report a volume of about 19,629 mm³ and a bounding box of 80 × 40 × 50 mm. If a generated script disagrees with these numbers, something is wrong even if it runs. Change thickness from 4 to 6 and the profile, the holes, and the checks all still hold.
I picked parts in increasing order of difficulty, to see where the models start to break:
Revolved geometry, standard-style features, tolerances
Spur gear (specified module, teeth, bore)
Mathematical geometry (involute profile), constraints
Electronics enclosure with lid and snap-fit
Multiple bodies, wall thickness, fits and clearances
Assembly relationships, thread representation, clearances
Each part comes with a written specification: dimensions, units, material, and intended manufacturing process (FDM 3D printing for parts 1, 4, and 5; CNC machining for parts 2 and 3).
Every model receives the same prompt for each part, built from four pieces: the part description with all dimensions in millimetres; the target library (CadQuery) and its version; a request to put all dimensions in a parameter block at the top; and a request to include basic validity checks.
I test two conditions. In the first, the model gets one attempt. In the second, I give the model the error message or a plain description of the failed check and allow up to three repair prompts. This mirrors how people actually use these tools.
For every run I record the exact model name and version, the test date, the Python and CadQuery versions, the operating system, and any printer, slicer, and material used. All prompts and raw outputs are saved unedited in a repository.
I define these rules before looking at any output, so I cannot bend them to fit the results. The thresholds are my own choices for this small test.
I score each output from 0 to 5 on five criteria, where 0 means it fails completely, 3 means it is usable after manual edits, and 5 means it passes with no edits.
Do the dimensions and features match the specification?
Does changing a parameter update the model correctly?
Would it print or machine without redesign?
Would a reviewer accept the design decisions (fits, wall thickness, load paths)?
A valid CAD model or a clean STEP export does not prove that a part can be made. In this article, a digital manufacturability evaluation means I check the geometry against the process rules below. A physical evaluation means a part is actually printed or machined. Unless I say a part was physically made, every manufacturability result is digital.
I use two layers of checks. First, automated checks in code: is it one valid solid, is the volume positive and close to a hand calculation, do the bounding box dimensions match the specification, and does it export cleanly to STEP and STL?
Second, an engineering review of the kind taught in a design class.
For design for manufacturing (DFM) thinking, I lean on Geoffrey Boothroyd, Peter Dewhurst, and Winston A. Knight, Product Design for Manufacture and Assembly, 3rd ed. (CRC Press, 2011), and on Karl T. Ulrich, Steven D. Eppinger, and Maria C. Yang, Product Design and Development, 7th ed.
(McGraw-Hill Education, 2020), which has a chapter on design for manufacturing and supply chain. For additive manufacturing constraints I use Ian Gibson, David Rosen, and Brent Stucker, Additive Manufacturing Technologies: 3D Printing, Rapid Prototyping, and Direct Digital Manufacturing, 2nd ed. (Springer, 2015), which includes a chapter on design for additive manufacturing.
For dimensions and fits, I check tolerances against David A. Madsen, David P. Madsen, and Dennis A. Schwartz, Geometric Dimensioning and Tolerancing: Principles and Practices, 10th ed. (Goodheart-Willcox, 2021), which follows the ASME Y14.5-2018 standard. For basic design calculations such as bolt sizing, I use Richard G. Budynas and J. Keith Nisbett, Shigley’s Mechanical Engineering Design, 11th ed.
(McGraw-Hill Education, 2020), which includes a chapter on screws, fasteners, and nonpermanent joints.
The rules below are common rules of thumb, so always confirm the limits for your own printer, material, and machine shop.
These are known risks in code generation and CAD scripting, not findings from my tests. In Part 2, I will report only failures I actually observed, and for each one I will say what the model did, how I detected it, and whether the repair worked.
1. Invented or unsupported function calls. Code-generating models can produce code that reads well but fails when run. Mark Chen et al., Evaluating Large Language Models Trained on Code (arXiv:2107.03374, 2021), judged code models by functional correctness (does the program actually work?) rather than by text similarity, and reported limits such as difficulty with long chains of operations and with binding operations to variables. Calling CadQuery methods that do not exist is one form this can take in my setting.
2. Coordinate and workplane confusion. CAD scripting depends on knowing which plane you are sketching on and which way is “up.” A feature can end up on the wrong side of a part or at the wrong height.
3. Unit and dimension drift. A model may switch between millimetres and inches, or misread a diameter as a radius.
4. Hard-coded numbers. A script can look parametric because it has a parameter block, yet use raw numbers in the geometry code, which breaks design intent as soon as a value changes.
5. Operations that fail on real geometry. Fillets, chamfers, and shells can fail when the model picks the wrong edges or the geometry makes the operation invalid. This relates to the boundary-representation operations described in Section 2.
6. Looks right, but not manufacturable. A part can match the specification on paper and still have thin walls, unsupported overhangs, or no clearance for assembly.
7. Math-heavy parts. A spur gear needs a correct tooth profile, and small errors mean gears that will not mesh.
I will evaluate each generated CAD model using the same criteria to keep the comparison consistent. The evaluation will cover five test parts: an L-bracket, a shaft coupling, a spur gear, an electronics enclosure, and a bolt-nut-plate assembly.
I will evaluate the original output separately from the output produced after up to three repair prompts. Any manual corrections will be documented separately and will not count as an unmodified AI success.
No scores or comparative results are reported here because the experiments have not yet been completed. Part 2 will present the observations, measurements, and supporting evidence collected during the tests.
So, can AI write CAD? My hypothesis, as a student who spends a lot of time checking dimensions, is that it can write CAD code, and sometimes that code will produce a usable part, but “usable” will still depend on a human who understands the geometry, the manufacturing process, and the design intent. The test above is how I plan to find out whether that is true or just a comfortable guess.
What I believe so far is that the hard part of CAD was never typing. It is knowing what the part needs to do, how it will be made, and what could go wrong. If AI speeds up the first draft, the fundamentals taught in design, manufacturing, and tolerancing courses matter more, not less.