chore(rebar): Pier_T_rebar 작업 폴더 초기 구성 및 외부 의존 파일 통합
- Code\rebar_pipeline, review_pipeline, pier-program을 정션에서 실제 폴더로 전환 - Code\rhino_mcp 및 CLAUDE_rhino배경.md 추가, .mcp.json은 PYTHONPATH로 새 위치 사용 - pier-program 내부 .git 제거(이력은 backup\pier-program_20261028.bundle에 보관) - worktree 가이드 반영(CLAUDE.local.md, HANDOFF.md) - D:\Rhino-MCP 경로 참조를 새 위치로 치환 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
964a841de1
3978 files changed
+58013356
No files matched your search
@@ -0,0 +1,74 @@
|
||||
"""Read the coping top-step outline of D1 (front view) straight from the DXF geometry (2026-10-19, trial of geometry reading).
|
||||
Finds the two end-batter tip lines on layer CS-CONC-MAJR (|dx|~200, |dy| 1300..1900), chains the horizontal / vertical lines between their top
|
||||
ends, converts x to the pier axis (centre of the two tips) and the heights to EL with the 'EL. xx.xxx' label next to the highest step.
|
||||
Reads only. usage: python tools/extract_coping_outline.py <D1.dxf> <texts.json> [params.json] (params.json: compare with coping.top_steps)"""
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
|
||||
import ezdxf
|
||||
|
||||
dxf, texts = sys.argv[1], sys.argv[2]
|
||||
doc = ezdxf.readfile(dxf)
|
||||
L = [(e.dxf.start.x, e.dxf.start.y, e.dxf.end.x, e.dxf.end.y) for e in doc.modelspace() if e.dxftype() == "LINE" and e.dxf.layer == "CS-CONC-MAJR"]
|
||||
tips = [l for l in L if 150 < abs(l[2] - l[0]) < 250 and 1300 < abs(l[3] - l[1]) < 1900 and l[1] < 25000 and l[1] > 0]
|
||||
tips = sorted({(round(l[0], 1), round(l[1], 1), round(l[2], 1), round(l[3], 1)) for l in tips})
|
||||
if len(tips) != 2:
|
||||
sys.exit(f"expected 2 tip lines, found {len(tips)}: {tips}")
|
||||
top = lambda l: (l[0], l[1]) if l[1] > l[3] else (l[2], l[3]) # noqa: E731
|
||||
bot = lambda l: (l[2], l[3]) if l[1] > l[3] else (l[0], l[1]) # noqa: E731
|
||||
left, right = sorted(tips, key=lambda l: top(l)[0])
|
||||
cx = (bot(left)[0] + bot(right)[0]) / 2
|
||||
cur, end = top(left), top(right)
|
||||
hv = [(round(a, 1), round(b, 1), round(c, 1), round(d, 1)) for a, b, c, d in L if (abs(a - c) < 0.05 or abs(b - d) < 0.05)]
|
||||
steps, used = [], set()
|
||||
while abs(cur[0] - end[0]) > 0.5 or abs(cur[1] - end[1]) > 0.5:
|
||||
nxt = None
|
||||
for s in hv:
|
||||
if s in used:
|
||||
continue
|
||||
for p, q in (((s[0], s[1]), (s[2], s[3])), ((s[2], s[3]), (s[0], s[1]))):
|
||||
if abs(p[0] - cur[0]) < 0.5 and abs(p[1] - cur[1]) < 0.5 and q[0] >= cur[0] - 0.5 and (q[1] >= cur[1] - 0.5 or abs(q[0] - cur[0]) > 0.5):
|
||||
nxt = (s, q)
|
||||
break
|
||||
if nxt:
|
||||
break
|
||||
if not nxt:
|
||||
sys.exit(f"chain broken at {cur}")
|
||||
used.add(nxt[0])
|
||||
if abs(nxt[1][1] - cur[1]) < 0.05:
|
||||
steps.append([cur[0], nxt[1][0], cur[1]])
|
||||
cur = nxt[1]
|
||||
y_hi = max(s[2] for s in steps)
|
||||
els = [(t["text"], t["x"], t["y"]) for t in json.load(open(texts, encoding="utf-8")) if t["dwg"] == "D1" and t["text"].startswith("EL.")
|
||||
and abs(t["x"] - end[0]) < 1500 and 0 < t["y"] - y_hi < 1200]
|
||||
if len(els) != 1:
|
||||
sys.exit(f"need exactly one EL label next to the highest step, found {els}")
|
||||
el_hi = float(re.search(r"\d+\.\d+", els[0][0]).group()) * 1000
|
||||
res = [{"x0": round(a - cx), "x1": round(b - cx), "z": round(el_hi - (y_hi - y))} for a, b, y in steps]
|
||||
print("axis x =", round(cx, 1), "| EL label", els[0][0])
|
||||
for r in res:
|
||||
print(r)
|
||||
if len(sys.argv) > 3:
|
||||
ref = json.load(open(sys.argv[3], encoding="utf-8"))["coping"]["top_steps"]
|
||||
d = max(max(abs(a[k] - b[k]) for k in ("x0", "x1", "z")) for a, b in zip(ref, res)) if len(ref) == len(res) else None
|
||||
print("max difference from params coping.top_steps (mm):", d)
|
||||
|
||||
# ---- other coping dimensions from the same geometry
|
||||
other = {"length_bottom_tip_to_tip": round(bot(right)[0] - bot(left)[0]),
|
||||
"tip_bottom_rise": round(top(left)[1] - bot(left)[1]),
|
||||
"end_batter_top_inset": round(abs(top(left)[0] - bot(left)[0]))}
|
||||
arcs = {round(e.dxf.radius) for e in doc.modelspace() if e.dxftype() == "ARC" and e.dxf.layer == "CS-CONC-MAJR" and e.dxf.radius > 3000}
|
||||
other["soffit_radius"] = sorted(arcs)
|
||||
flat = [(a, b, c_, d) for a, b, c_, d in hv if abs(b - d) < 0.05 and 1800 < abs(c_ - a) < 2600 and abs((a + c_) / 2 - cx) < 600 and bot(left)[1] - 1700 < b < y_hi]
|
||||
flat = sorted({(round(f[0], 1), round(f[1], 1), round(f[2], 1)) for f in flat if f[1] < bot(left)[1] + 100})
|
||||
if flat:
|
||||
f = flat[0]
|
||||
other["flat_bottom_half_width"] = round(abs(f[2] - f[0]) / 2)
|
||||
other["z_bottom_flat"] = round(el_hi - (y_hi - f[1]))
|
||||
other["_flat_candidates"] = len(flat)
|
||||
sect = sorted({round(abs(c_ - a), 1) for a, b, c_, d in hv if abs(b - d) < 0.05 and 3000 <= abs(c_ - a) <= 3200 and a > 20000})
|
||||
other["width_y_candidates"] = sect
|
||||
print("other:", other)
|
||||
if len(sys.argv) > 3:
|
||||
print("params:", {k: ref_ for k, ref_ in json.load(open(sys.argv[3], encoding="utf-8"))["coping"].items() if k in other})
|
||||
Reference in new issue
Block a user