3D Design & PrintModel validated

Drawer Organizer: A Watertight STEP File Generated Straight From the Change Request

The whole spec for this part arrived as prose in a ServiceNow change request — every dimension, every hole position, and a list of checks the finished model had to survive. No sketching, no GUI: the interesting question was whether a written spec that precise could go straight to a manufacturable STEP file without a human touching the geometry.

Status: geometry is built and passes every check the ticket asked for, including the exact target volume. What has not happened yet is a test print — nothing here has been near a printer, so the structural claim is arithmetic, not evidence.

The Model

Drag to rotate. This is a tessellated preview of the same solid the STEP file contains — useful for eyeballing the pattern, not for measuring.

What It Has To Be

An open-top drawer organizer sized to a specific drawer, with elongated vertical diamond openings through all four walls. The diamonds are the point: they cut filament use meaningfully while leaving continuous material at every place the box actually carries load.

ParameterValueWhy it matters
Exterior165 × 148 × 70 mmFits the drawer; nothing may drift.
Wall / floor thickness2 mm eachFour or five perimeters at a typical 0.4 mm nozzle.
Internal opening161 × 144 mmUsable footprint after walls.
Internal usable height68 mm70 mm exterior less the 2 mm floor.
Diamond opening16 mm wide × 27 mm tallLong axis vertical, sharp top and bottom points.
RowsCentrelines at 19.5 and 51.5 mmLeaves 6 mm below, 5 mm between, 5 mm above.
Opening count60 total — 16/16/14/14Eight per row on the 165 mm walls, seven on the 148 mm walls.
TopCompletely openPrint-in-place, no supports.

The diamond orientation is doing structural work, not just decoration. Points at top and bottom mean every opening is self-supporting when printed vertically — the overhang angle never goes shallow enough to need support material — and the material left between openings forms continuous diagonal ribs rather than isolated posts.

Technical Preview

Generated from the same parameters as the solid, so the drawing cannot drift out of sync with the model:

Technical drawing of the drawer organizer: isometric view showing the diamond pattern on all walls with overall dimensions of 165 by 148 by 70 millimetres, plus a cross-section showing the open top and solid 2 millimetre floor
Isometric view with overall dimensions, the 16 × 27 mm diamond callout, and a cross-section through the 165 mm walls showing the open top and the solid 2 mm floor.

How It Was Built

Parametrically, in CadQuery — Python driving the OpenCASCADE kernel. That matters for a spec this dimension-heavy: every number in the table above is a named constant at the top of one file, so a dimension change is an edit and a re-run, not a re-model.

The construction is deliberately boring, because boring booleans are the ones that stay watertight:

  1. Build the solid outer box, then cut a single rectangular cavity for the interior. The cavity is deliberately extended past the rim so the boolean never has to resolve two coincident faces — that is the case that quietly produces invalid geometry.
  2. Build each of the 60 diamonds as its own four-sided prism, oriented to the wall it passes through and overshooting by 1 mm on both sides so it is a clean through-cut rather than a face-grazing one.
  3. Subtract them one at a time and export STEP AP214.

The whole run takes about six seconds, which is the real argument for doing it this way — a dimension I got wrong costs one re-run, not an afternoon.

Validation

The ticket listed the checks it wanted, so validation re-imports the exported STEP file from disk and tests that, rather than testing the in-memory model that produced it. A model that is valid in the session but exports badly is exactly the failure worth catching.

CheckRequiredMeasured
Bounding box165 × 148 × 70 mm165.000 × 148.000 × 70.000 mmPass
Number of solids11Pass
Model validitytruetrue (BRepCheck_Analyzer)Pass
Watertight / manifoldrequired1 closed shell; every edge bounded by exactly 2 facesPass
Solid volume≈ 106,968 mm³106,968.000 mm³Pass
Volume reduction≈ 19.5%19.505% (against 132,888 mm³ unperforated)Pass
Opening count16 / 16 / 14 / 1416 front, 16 back, 14 left, 14 right — 60 totalPass
No disconnected fragmentsrequiredsingle solid, single shellPass
No openings through the bottomrequiredfloor solid on a 3 mm probe gridPass
Corners and top rim intactrequiredall four vertical corners solid full height; rim and bottom perimeter unbrokenPass
Topology (independent)genus 60 — one closed surface with 60 through-holesEuler characteristic −118 on the exported meshPass
Diamond geometry16 × 27 mm, sharp vertical pointsextents confirmed; bounding-box corners solid, so the profile is a diamond and not a rectanglePass

Two of those checks are worth calling out. The volume came out at 106,968.000 mm³ against a target of “approximately 106,968” — not approximately, exactly, because none of the 60 cutouts overlaps a corner or another cutout, so the closed-form arithmetic and the kernel have to agree. If they had disagreed, something had silently moved.

The topology row is the check I trust most, because nothing about it depends on knowing where the holes were supposed to be. Tessellate the solid, count vertices, edges and faces, and the Euler characteristic comes out at −118 — which for a single closed surface means genus 60, sixty holes passing clean through. A cutout that failed to penetrate, or two that merged into one, would change that number. It is the same count arrived at from the opposite direction.

The other is the diamond-versus-rectangle check. Extent tests alone cannot tell those two shapes apart — a 16 × 27 mm rectangle passes every extent test a diamond does. Probing just inside the corner of the opening’s bounding box and confirming it is still solid is what actually proves the profile tapers to points.

On Not Needing Another Model For This

The change request allowed for the possibility that I could not produce real CAD, and asked for a plan to hand the job off to another API or MCP server if so. That turned out not to be necessary, and the reason is worth recording: generating a STEP file is not a rendering problem, it is a geometry-kernel problem. CadQuery installs as a normal Python package and brings OpenCASCADE — the same kernel underneath FreeCAD — with it. Writing the script and running it are both things that happen locally.

A hand-off would only earn its keep for work a kernel genuinely cannot do: organic surfacing, topology optimization, or generating a mesh from a text description rather than from dimensions. For a fully dimensioned part like this one, another model in the loop would add a round trip and a second thing to verify, and would still have to produce the same booleans.

Files

What Is Still Open