L1 · DS-110

Constraints & Valid Ranges: A Part Family

Build a real parametric part that lands inside a fixed spec envelope: drive its dimensions so the solid's bounding box and material volume both fall within tolerance of the published datasheet, proving the part is a legal member of the family rather than an out-of-range variant.

01
Challenge

Try this first — before any explanation.

The Bench loads a mounting plate the kernel happily builds and renders in 3D - a solid 80x50x14 block, no hole. It looks like a part. But the family datasheet says every legal plate is exactly 80x50x10 mm with a single Ø12 bore straight through the 10 mm thickness. Run it: the autograder measures result.bounding_box().size and reports the Z is 14, not 10 - 4 mm out of envelope - and result.volume is 56000 mm3 when a legal plate is 38869 mm3, because the bore is missing entirely. The kernel never complains; build123d will build any block you ask for. Out-of-range is not a crash, it is a part that exists but is not in the family. Pull the height down to 10 and cut the Ø12 hole, and the measured envelope snaps onto the datasheet.

The Bench

Real build123d on the OpenCascade kernel (Pyodide + OCP.wasm), rendered in 3D. Define result as a build123d Part/Solid. The autograder reads result.bounding_box().size and result.volume and compares both to the family datasheet: the bounding box must be 80x50x10 mm (tol 0.1) and the volume must match a 10 mm plate with a single O12 through-bore (38869 mm3). The kernel will build any block you ask for - out-of-envelope is your job to catch, not the kernel's.

PARAMETRIC CAD

Constraints & Valid Ranges: A Part Family

Real build123d on the OpenCascade kernel (Pyodide + OCP.wasm), rendered in 3D. Define result as a build123d Part/Solid. The autograder reads result.bounding_box().size and result.volume and compares both to the family datasheet: the bounding box must be 80x50x10 mm (tol 0.1) and the volume must match a 10 mm plate with a single O12 through-bore (38869 mm3). The kernel will build any block you ask for - out-of-envelope is your job to catch, not the kernel's.

02
Model

The idea, built visually.

The kernel just built that block without a word of protest. That is the thing to notice: a parametric script does not have an opinion about what a real part is - ask for 80 by 50 by 14 and you get exactly that solid, rendered and shaded and wrong. Every parametric part is not one part, it is a whole space of parts, and only a slice of that space is the family you are allowed to ship. The datasheet draws the fence. Two things define this plate: its bounding box must read 80 by 50 by 10, and its volume must read what a 10 mm plate minus a 12 mm bore actually displaces. Get the height wrong and the bounding box catches you - the part is too tall, out of envelope. Forget the bore and the volume catches you - the block is solid where there should be a hole, and a box minus nothing has too much material. Volume is the honest witness here: the bounding box cannot see the hole at all, only the volume can. So you drive height to ten, you subtract a cylinder of radius six through the full thickness, and the two measurements - the outside and the inside - both land on the datasheet. That is what makes it a member of the family, not a lucky-looking block.

▣ Stage animation: Same dark-navy identity; warm --accent-warm (#FF9E4C) means out-of-envelope. Open on the kernel quietly building a tall solid block, a faint datasheet card pinned beside it reading 80 x 50 x 10, bore O12. A measuring caliper drops onto the block's Z and reads 14 in warm orange; the number pulses and a label 'out of envelope: +4mm' slides in. The block's top face glides down 4mm, Z reads 10, the caliper flashes navy-blue: in range. Cut to the inside: a translucent cross-section shows the block is solid all the way through; a volume gauge fills past the datasheet line into warm territory, '56000 > 38869'. A cylinder of radius 6 sweeps down through the thickness and boolean-subtracts; the bore opens, the gauge drains back onto the datasheet line and flashes blue. Pull back: outside box and inside cavity both glowing navy, two ticks - 'bbox matches' and 'volume matches'. Kinetic type: 'a member of the family, not a lucky-looking block.'

03
Guided practice

Build it up, step by step.

Work in build123d algebra mode - objects you add and subtract. Step A (worked): build just the plate body to spec. result = Box(80, 50, 10) gives a solid whose Box(length, width, height) maps to X, Y, Z; bounding_box().size will read (80, 50, 10). Callout: Box centers on the origin, and that is fine - the autograder reads the box SIZE, not its position. Step B (cut the bore): a through-hole is a boolean subtract of a cylinder. result = Box(80, 50, 10) - Cylinder(radius=6, height=10) - Cylinder defaults to its axis along Z, height spanning the full 10 mm thickness, so it punches clean through. Note radius=6 because the datasheet bore is O12 (diameter), and volume drops by pi66*10 = 1131 mm3. Step C (own the envelope): confirm both numbers yourself before submitting - print(result.bounding_box().size) must read about (80, 50, 10) within 0.1, and print(result.volume) must read about 38869 within a few mm3. If the bbox Z is 14 you never pulled the height down; if the volume is 40000 the cut never happened; if the volume is 38869 but bbox is wrong, you sized the plate wrong. Make both land, then submit.

04
Feedback

How the Bench grades your run.

PASS WHEN PASS - bounding box reads 80x50x10 mm (within 0.1) and volume reads 38869 mm3 (within 5) - the plate is a legal member of the family: in envelope outside, correct bore inside.

  • OUT OF ENVELOPE: bounding box Z is 14 mm but the datasheet says 10. Build the plate at the spec height - Box(80, 50, 10) - so the outer envelope matches.
  • MISSING BORE: bounding box is correct but volume is 40000 mm3, the value of a solid block. The bore is not cut. Subtract Cylinder(radius=6, height=10) so the volume drops to 38869.
  • WRONG BORE SIZE: volume is off by more than 5 mm3 - your cylinder radius is not 6. The datasheet bore is O12, so radius=6; pi*6*6*10 = 1131 mm3 must come out of the block.
  • BORE TOO SHALLOW: volume is between 38869 and 40000 - the cylinder height is less than 10, so the hole does not go all the way through. Set Cylinder(height=10) to pierce the full thickness.
  • WRONG FOOTPRINT: bounding box X or Y is not 80x50. Both in-plane dimensions are fixed by the datasheet - Box(80, 50, 10) - before you touch the bore.
05
Retrieve & space

Bring back what you've already mastered.

  • build123d recall: write the one line that builds an 80x50x10 mm plate and the one line that cuts a O12 through-hole in it - Box(80,50,10) - Cylinder(radius=6, height=10). Name which call sets the outer envelope and which one changes only the volume.
  • From M2.1 (driven dimensions): rewrite the bore as a parameter - bore_d = 12; result = Box(80,50,10) - Cylinder(radius=bore_d/2, height=10) - so the radius does the math itself instead of a literal 6.
  • Measurement recall: which property would catch a missing hole, result.bounding_box().size or result.volume, and why can the bounding box never see an internal bore?
06
Mastery gate

What you must demonstrate to advance.

Submit a build123d result whose result.bounding_box().size is 80x50x10 mm within 0.1 AND whose result.volume is 38869 mm3 within 5 - both the outer envelope and the inner material must land on the datasheet in one run. The non-negotiable is that the bore is actually cut: a solid block can match the bounding box yet fail volume, and shipping a plate with no hole is the dangerous miss. Pass = Module 2 complete, unlocks Module 3 (Assemblies & Mechanisms).

07
Project

How this feeds your build.

Not a capstone lesson, but the gate that makes the rest of the course safe. In M3 you locate and bolt this exact plate into an assembly through that very bore, so its envelope guarantees the mating part meets a real, in-spec face. In M4, MuJoCo-WASM only ever receives geometry whose volume and footprint are known-good, so a sim failure is a physics problem, not a malformed body. In the M5 capstone, this same bbox+volume envelope is the fence that keeps the optimizer resizing your device inside the space of parts that can actually be built. A member of the family, not a lucky-looking block.