Files
OneCAD/tools/freecad-oracle/run.sh
T
e12758ff91 Public reference tests: analytic and FreeCAD expected values (#310)
The oracle no longer uses Fusion measurements. tests/oracle/<case>/ now holds the 76 recipes
(our own format, with recorded measurements and tool-specific fields removed) and an
expected.json per case:

- 55 analytic cases: closed-form values from tools/oracle-analytic/ (stdlib Python, formulas
  in each case's "method").
- 21 FreeCAD cases: the same recipe built with FreeCAD's public scripting API by
  tools/freecad-oracle/ (an external program, not a dependency), with a reference.stl for 20.

solvecraft-cli oracle compares body count, volume, area, centre of mass, bbox, face counts
where the geometry fixes them, and, against reference.stl, the sampled Hausdorff distance and
the principal moments (spatial.rs from #301). cargo xtask oracle reads tests/oracle, writes
docs/oracle.md with the source of each value, and supports known_failure marks for tracked
bugs. CI runs it on every PR; a manual workflow regenerates the FreeCAD values. step-corpus,
seam normalisation and the through-all emulation, which only existed to compare with Fusion,
are removed.

75/76 pass; 75-sm-bracket-holes is a known failure (#296).


Claude-Session: https://claude.ai/code/session_01RjGw4gA5ZvKrU8MQP6sBgT

Co-authored-by: bherbruck <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-12 10:43:43 -04:00

50 lines
1.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# Build reference cases with FreeCAD (as an external program) and print or write the results.
#
# tools/freecad-oracle/run.sh [--write] <case-dir>...
#
# Without --write: prints one line per case. With --write: writes <case>/expected.json and
# <case>/reference.stl (refuses to overwrite an expected.json whose source is "analytic").
# freecadcmd is found via $FREECADCMD, then `freecadcmd` on PATH, then the local AppImage.
set -euo pipefail
here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
write=0
cases=()
for a in "$@"; do
case "$a" in
--write) write=1 ;;
-h|--help) sed -n '2,9p' "$0"; exit 0 ;;
*) cases+=("$a") ;;
esac
done
[ ${#cases[@]} -gt 0 ] || { echo "usage: $0 [--write] <case-dir>..." >&2; exit 2; }
fc="${FREECADCMD:-}"
if [ -z "$fc" ]; then
if command -v freecadcmd >/dev/null 2>&1; then fc="$(command -v freecadcmd)"
elif command -v FreeCADCmd >/dev/null 2>&1; then fc="$(command -v FreeCADCmd)"
else fc="$here/squashfs-root/usr/bin/freecadcmd" # an AppImage extracted here (gitignored)
fi
fi
[ -x "$fc" ] || { echo "freecadcmd not found (set FREECADCMD)" >&2; exit 2; }
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT
status=0
for c in "${cases[@]}"; do
c="${c%/}"
name="$(basename "$c")"
out="$tmp/$name.json"
stl=""
[ $write = 1 ] && stl="$tmp/$name.stl"
ORACLE_CASE="$c" ORACLE_OUT="$out" ORACLE_STL="$stl" \
"$fc" -c "exec(open('$here/build.py').read())" </dev/null >"$tmp/$name.log" 2>&1 || true
if [ ! -s "$out" ]; then
echo "$name: FreeCAD produced no result"; tail -5 "$tmp/$name.log"; status=1; continue
fi
WRITE=$write CASE="$c" OUT="$out" STL="$stl" "$fc" -c "exec(open('$here/emit.py').read())" </dev/null 2>&1 \
| grep -v '^FreeCAD\|^(c) \|^$' || status=1
done
exit $status