results · featuretree

featuretree on the NIST test parts: results

2026-09-29 · Dan Newcome · punkfab/featuretree (MIT) · preprint 10.5281/zenodo.22848792

featuretree turns a STEP solid into an editable feature tree for FreeCAD, Onshape or build123d, and checks every recovery by rebuilding it. A tree that rebuilds the part is VERIFIED. One that doesn't is labelled PARTIAL, with the error reported. This post is the scorecard: every distinct part geometry in NIST's MBE PMI test set, with time, complexity, accuracy, and how well the recovered tree matches what the designer actually drew.

The short version: every part now comes back as an editable tree that overlaps the original by at least 93.5%, averaging 97.6%, up from 65%. None was wrongly accepted. The VERIFIED count didn't move: it's still 3 of 11, because the bar also got higher. Our own checks caught our new recogniser accepting two parts it shouldn't have, and we made the bar stricter rather than keep the better-looking number.

All eleven NIST test parts, each original in grey beside its recovered feature tree rebuilt in teal, labelled with verdict and overlap. Three are VERIFIED at 99.67 to 100 percent; eight are PARTIAL between 93.5 and 99.0 percent. The recovered CTC-02 housing shows visible stair-stepping on its drafted walls.

Scorecard

NIST doesn't define a score for feature recognition. These test cases exist to check how CAD translators carry tolerances and annotations (PMI). So the criteria below are ours, stated so anyone can re-compute them from the repo:

CriterionResult
Coverage: distinct NIST test geometries run (CTC-01 to 05, FTC-06 to 11)11 / 11
Editable tree returned (none refused, none crashed)11 / 11
VERIFIED: volume within 0.5%, size within 0.05 mm, and overlap (IoU) at least 99.5%3 / 11
False accepts: VERIFIED but independently measured below 99.5% overlap0
Overlap with the input, all parts (mean / worst)97.6% / 93.5% (was 65.0% / 7.4%)
Parts above 95% / above 99% overlap10 / 11 · 4 / 11
Recognition time (median / slowest / whole set)152 s / 562 s / 29 min
Complexity: B-rep faces in → feature operations out2,727 → 431
Dimensioned holes found, vs the designer's PMI97 / 196
Standard sizes named correctly (of holes found)68 / 74
Unit system (inch vs metric) inferred correctly9 / 11

Overlap here is intersection over union (IoU) between the original solid and the rebuilt tree. We measure it without CAD Boolean operations, by classifying thousands of sample points against both solids, with the recogniser's own transform undone so the comparison is exact. Booleans turned out to be unreliable on exactly the parts that fail. That story is in the first post.

Every part

PartFaces inOps outTimeOverlap beforeOverlap nowVerdictHoles vs PMI
CTC-011393986 s99.8%99.8%VERIFIED7/7
CTC-0266389562 s7.4%93.5%partial2/7
CTC-031393372 s36.1%95.2%partial0/11
CTC-0451793194 s30.8%99.0%partial36/41
CTC-052084058 s14.5%97.2%partial1/1
FTC-0614418166 s59.6%98.2%partial0/22
FTC-0726921194 s95.5%95.4%partial4/27
FTC-0827032152 s95.9%98.7%partial16/16
FTC-091584018 s99.7%99.7%VERIFIED29/30
FTC-1021425241 s76.0%97.3%partial0/32
FTC-116119 s100%100%VERIFIED2/2

"Before" is the published first post. "Ops out" counts the pads, pockets, cuts and revolves in the recovered tree (sketches not counted). Time is recognition only, one part at a time. FTC-11 is a two-feature ring and shouldn't carry much weight.

01 / Slice it, don't guess it

The first version assumed a part is one profile swept along one axis, then carved. That works on machined plates like CTC-01 and FTC-09. It fails on anything built up in levels: a pan with a flange, a housing with bosses at several heights, a bracket bent from sheet. Those came back as fragments, at 7% to 60% overlap.

The new path treats a part as a stack of 2.5D layers. Along each principal axis it takes exact cross-sections. It starts at every flat face perpendicular to the axis, where a step or floor can begin, then splits further wherever the section's shape changes between samples, since a boss merging into a wall often ends on a curve with no flat face to mark it. Layers that look the same merge. Each layer becomes one sketch and one pad, drafted if its slices taper, and holes are linked through the layers and cut once. That's the whole change behind the "overlap now" column: CTC-05 went from 14.5% to 97.2%, and CTC-04 from 30.8% to 99.0%.

02 / Our checks caught our own recogniser

The first run with layered recognition looked great: 7 of 11 VERIFIED. It was wrong. At the time, VERIFIED meant the rebuilt tree matched the original on volume and on size. More candidates per part means more chances for errors to cancel: material missing in one place and extra in another can add up to the right volume. Measured independently, two of those seven overlapped their originals by only 95.0% (CTC-03) and 93.7% (FTC-07). Two more fell just short.

We'd predicted this failure in our own preprint and recommended an overlap test as the fix, but hadn't shipped it. Now VERIFIED also needs 99.5% overlap, measured without Booleans on every candidate. The count went back to 3, with no false accepts. We'd rather publish 3 we can defend than 7 we can't.

03 / Defects our checks found

DefectFound byEffect before the fix
Volume and size can agree while the shape is wrongindependent overlap measurement2 parts wrongly VERIFIED (95.0%, 93.7%)
A layer whose section wouldn't close was silently dropped, and everything above it sanksize checkCTC-02 17.27 mm short, no warning
When nothing verified, the closest-volume candidate was returned, not the best-overlapping oneoverlap measurementFTC-08 at 93.5% instead of 98.7%
Separate regions in one layer were stacked on top of each otherrebuild + render reviewFTC-07's floor 2.5 mm up and out of the part
Hole cuts placed in the rotated working framerebuild + render reviewholes 115 mm outside FTC-07
Hole outline taken from the smallest slice, which was a filletvolume checkFTC-08 under-cut 1.15 mm per side
Geometry kernel crash during recognition took the whole part with itcorpus runCTC-02 "no output"
Wire length re-measured on every point sampleprofiler180 s of a 183 s run
Wrong trees published: 0

Each of these is now a test or a standing check in the harness, so the next recogniser change has to pass them.

04 / Design intent, scored against the designer

A tree that rebuilds the part still reads like a machine wrote it. Holes are arcs inside generic cuts, and every size is a bare float. featuretree re-expresses it the way a designer would: holes, bolt circles and rows, the unit system, and the standard drill each diameter most likely is. NIST's AP242 files carry the designer's own dimensions, tolerances and datums, so this can be scored, not just demonstrated.

On the three VERIFIED parts it finds 38 of 39 dimensioned holes and names all 36 sizes the way the drawing does. A 3.969 mm hole comes back as a 5/32" drill where the drawing says .156. Across all eleven parts it finds 97 of 196 holes, and PARTIAL trees can still carry intent: all 16 of FTC-08's holes and 36 of CTC-04's 41. It misses every hole on FTC-06, FTC-10 and CTC-03, where the holes are threaded, chamfered or split across layers and don't slice as clean circles. It gets the unit system wrong on two metric parts whose overall dimensions happen to land on an inch grid.

What's still hard: CTC-02

CTC-02 is a cast housing, and the tool was built around machined parts. It has 663 faces, against 139 for CTC-01, including 158 cones (drafted walls and bosses, so it releases from a mould) and 58 freeform or spherical blends. A stack of layers along one axis approximates it rather than representing it. The drafts become a staircase (visible in the render), the side bosses become layer outlines instead of features on their own axis, and 1,369 section curves are approximated by arcs. It reaches 93.5% overlap and takes over 9 minutes. Next up:

Who did what

This was iterative, not one-shot. We steered the heuristics with Claude over many rounds, pushing on performance, correctness and generality. Claude wrote and debugged the code and ran the evaluation. Once the heuristics exist, recovery is hands-off: a STEP file goes in, a feature tree and a verdict come out.

The scorecard is generated by paper/figures/results_report.py from the persisted recovered trees, so every number here can be re-derived from the repo at commit 270e60d.

Everything is open in punkfab/featuretree. Got a STEP file that should be an editable model? Start a project →