passages: smoothed open-air shell joins (L110, v257) - partial, not merged
Bands = end profiles of per-control-span shell capsules (~9.35 m pitch = span spacing). Shell now smooth-unions adjacent spans over 6 m and reuses the interior chord distance; a 0.60 m clearance fades in 5-20 m from each mouth. Close-ups: bands reduced but still visible on part of the exposed shell. Cost vs L109: near-ready +8..+12% (FI 0.88 -> 1.00, TN 0.92 -> 1.01 s @W12). Audits, Clang/GCC determinism, fast tier and Linux UE build pass. Kept on its own branch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
1 parent
5ea01988c4
commit
bf39712792
397 files changed
+7754
-128
No files matched your search
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Build review sheets for every L110 before/after passage capture."""
|
||||
from __future__ import annotations
|
||||
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[4]
|
||||
CAPTURES = Path(__file__).resolve().parent / "captures"
|
||||
SHEETS = CAPTURES / "contact-sheets"
|
||||
GROUPS = {
|
||||
"openair-view-1": ("*-openair-*-view-1.png", "3x3"),
|
||||
"openair-view-2": ("*-openair-*-view-2.png", "3x3"),
|
||||
"openair-view-3": ("*-openair-*-view-3.png", "3x3"),
|
||||
"openair-closeups": ("*-openair-*-closeup-*.png", "3x4"),
|
||||
"mouths": ("*-*-*-*-mouth.png", "3x2"),
|
||||
"stations": ("*-station-*.png", "3x3"),
|
||||
}
|
||||
|
||||
|
||||
def build(variant: str, group: str, pattern: str, layout: str) -> int:
|
||||
files = sorted((CAPTURES / variant).glob(pattern))
|
||||
if not files:
|
||||
raise RuntimeError(f"no images matched {variant}/{pattern}")
|
||||
columns, rows = (int(value) for value in layout.split("x"))
|
||||
scale = "480:270"
|
||||
output = SHEETS / f"{variant}-{group}.png"
|
||||
command = ["ffmpeg", "-hide_banner", "-loglevel", "error", "-y",
|
||||
"-f", "image2", "-pattern_type", "glob", "-framerate", "1",
|
||||
"-i", str(CAPTURES / variant / pattern), "-vf",
|
||||
f"scale={scale},tile={columns}x{rows}:nb_frames={columns*rows}:padding=6:margin=6",
|
||||
"-frames:v", "1", str(output)]
|
||||
result = subprocess.run(command, cwd=ROOT, check=False,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
if result.returncode:
|
||||
raise RuntimeError(f"ffmpeg failed for {variant}/{group}: {result.stderr.strip()}")
|
||||
return len(files)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
SHEETS.mkdir(parents=True, exist_ok=True)
|
||||
rows = []
|
||||
for variant in ("before", "after"):
|
||||
for group, (pattern, layout) in GROUPS.items():
|
||||
count = build(variant, group, pattern, layout)
|
||||
rows.append(f"- [{variant} {group}]({variant}-{group}.png) — {count} views")
|
||||
(SHEETS / "INDEX.md").write_text("# L110 capture contact sheets\n\n"
|
||||
+ "\n".join(rows) + "\n", encoding="utf-8")
|
||||
print(f"contact sheets={len(rows)} captures={sum(
|
||||
int(row.rsplit('— ', 1)[1].split()[0]) for row in rows)}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in new issue
Block a user