"""Shared helpers for the gate checkers (imported inside Rhino 8). Checkers read only EXPECTED_PATH (independent drawing values) and never the generator params. """ import json from Rhino.DocObjects import ObjectEnumeratorSettings def load_expected(path): return json.load(open(path, encoding="utf-8")) def all_objects(doc): """All live objects incl. hidden/locked (doc.Objects alone skips hidden ones).""" s = ObjectEnumeratorSettings() s.HiddenObjects = True s.LockedObjects = True return list(doc.Objects.GetObjectList(s)) def chain(spec, base=0.0): """Expand a dimension chain: start offsets (cumulative) then groups [[n, pitch], ...] from the last point.""" pts, z = [], base for s in spec["start"]: z += s pts.append(z) for n, p in spec["groups"]: for _ in range(n): z += p pts.append(z) return pts def series(spec): """Expand {start, pitch, n} (or a literal list) into a list of values.""" if isinstance(spec, list): return list(spec) return [spec["start"] + spec["pitch"] * i for i in range(spec["n"])] def row(spec): """Bar positions: two end bars plus a regular series.""" return sorted(list(spec["ends"]) + series(spec)) def ychain(spec, half): """Section chain measured from the -Y face: listed first bars (absolute), then n x pitch from the last of them, then the last bar at `end`; returned relative to the section centre (minus `half`).""" pts = list(spec["start"]) pts += [pts[-1] + spec["pitch"] * k for k in range(1, spec["n"] + 1)] + [spec["end"]] return [y - half for y in sorted(pts)] def write_result(path, results, extra=None): summ = dict(total=len([r for r in results if r["result"] != "INFO"]), passed=sum(r["result"] == "PASS" for r in results), failed=sum(r["result"] == "FAIL" for r in results)) summ.update(extra or {}) json.dump(dict(summary=summ, results=results), open(path, "w", encoding="utf-8"), ensure_ascii=False, indent=1) print(json.dumps(summ, ensure_ascii=False)) return summ