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:
ahnyongjooandClaude Sonnet 5.5 committed 2026-10-28 11:20:18 +09:00
commit 964a841de1
3978 files changed
+58013356

No files matched your search

+66
View File
@@ -0,0 +1,66 @@
"""Add the column rebar (G2: P1~P5) to the app pier '새재1교P1' (ring builder column_rebar_ring.py, Okseong options).
params = 판독/g2_values.json (front chains / section reading) + schedule; expected = schedule L / N / r (구조도(4)) and the front
dimension chains, typed in by hand. Backs up params.json / expected.json to data/새재1교P1/backup/2026-10-15_g2/ first.
Refuses if G2 is in scope.
"""
import json
import shutil
import sys
from pathlib import Path
HERE = Path(__file__).resolve().parent
D = HERE.parents[1] / "Code" / "교각모델링앱" / "data" / "새재1교P1"
V = json.loads((HERE / "판독" / "g2_values.json").read_text(encoding="utf-8"))
P = json.loads((D / "params.json").read_text(encoding="utf-8"))
X = json.loads((D / "expected.json").read_text(encoding="utf-8"))
if "G2" in P["scope"]:
sys.exit("G2 already in scope")
bk = D / "backup" / "2026-10-15_g2"
bk.mkdir(parents=True, exist_ok=True)
for f in ("params.json", "expected.json"):
shutil.copy2(D / f, bk / f)
h, z = V["hoops_chain"], V["hoop_zones"]
cut, zones = 0, []
spec = {"P3": ("coupler_half", 3073.0, 80.0, 1003.5), "P4": ("coupler_half", 3078.0, 65.0, 1000.5)} # r = ring 975 + P1 r 16 + hoop r 12.5 / 9.5 (table r 1.004 / 1.001 rounded)
for mark, n in z:
t, a, gap, r = spec[mark]
zones.append({"mark": mark, "type": t, "levels": h[cut:cut + n], "a": a, "gap": gap, "radius": r})
cut += n
assert cut == len(h)
P["scope"] = ["G1", "G2", "G5"]
P["builders"]["G2"] = "column_rebar_ring.py"
P["rebar_marks"] = {"P1": {"dia": "H32", "shape": "VI"}, "P2": {"dia": "H32", "shape": "VI"},
"P3": {"dia": "H25", "shape": "coupler_half"}, "P4": {"dia": "H19", "shape": "coupler_half"},
"P5": {"dia": "H19", "shape": "tie-90/135"}}
P["rebar_marks_src"] = "구조도(4) 철근 재료표·상세 (기둥 P1~P5)"
P["column_rebar"] = {
"form": "ring",
"main": {"mark": "P1", "count": 49, "start_deg": 0.0, "radius": 975.0, "hook_leg_z": 10182.0, "bend_r": 340.0,
"hook_leg": 500.0, "straight_from": 10522.0, "straight_len": 21835.0, "inner": {"mark": "P2", "radius": 930.0},
"src": "단면 r 975 / 930 × 49 (7.347° 간격); 상세 a 21,835 r 340 c 500; 다리 EL 10.182 = 정면 작도 (기초 하면 + 150)"},
"hoops": {"radius": 1003.5, "zones": zones,
"src": "사슬 '띠철근외측' 72단(100 | 1.300 | 4@300 | 18@150 | 36@300 | 9@300 | 4@300); 구간 P3 5 / P4 18 / P3 36 / P4 9 / P3 4 "
"(수량 45·27 일치, 표지선 교번 [추론]); 상세 r 1.004 / 1.001 = 1,003.5 / 1,000.5(주철근 바깥 접함), a, b(커플러); 커플러 90°/270° [추론]"},
"ties": {"mark": "P5", "shape": "90-135", "levels": V["ties_chain"], "straight": 2050.0, "leg": 200.0, "tail": 165.0,
"y_lift": 19.0, "design_length": 2515.0,
"src": "사슬 '크로스타이' 40단; 상세 a 200, b 2,050, c 165, d 100; Y +19 [추론], 90°/135° 교번 [추론], 꼬리 = c [추론]"},
}
X["checkers"]["G2"] = "g2_ring.py"
X["negative"]["G2"] = [{"mark": "P1", "d": [5, 0, 0]}, {"mark": "P3", "d": [0, 0, 5]}]
X["G2"] = {"schedule_L": {"P1": 22869, "P2": 22869, "P3": 6306, "P4": 6286, "P5": 2515},
"schedule_n": {"P1": 49, "P2": 49, "P3": 45, "P4": 27, "P5": 80},
"dia": {"P1": 32, "P2": 32, "P3": 25, "P4": 19, "P5": 19},
"main": {"mark": "P1", "radius": 975, "divisions": 49, "start_deg": 0.0, "bottom_above_footing": 150,
"top_parts": [150, 340, 21835], "inner": {"mark": "P2", "radius": 930}},
"hoop_chain": {"start": [100, 1300], "groups": [[4, 300], [18, 150], [36, 300], [9, 300], [4, 300]]},
"hoop_zones": [["P3", 5], ["P4", 18], ["P3", 36], ["P4", 9], ["P3", 4]], "r_hoop": 1004,
"r_hoop_by_mark": {"P3": 1004, "P4": 1001},
"tie": {"mark": "P5", "chain": {"start": [100, 950], "groups": [[1, 600], [7, 300], [15, 600], [14, 300], [2, 600]]},
"per_level": 2, "offset": 0, "y_lift": 19},
"no_fillet_marks": ["P1", "P2", "P3", "P4"],
"src": "재료표 L·N·r; 단면 r 975 / 930 DIVISION 49; 사슬 '띠철근외측'·'크로스타이' (기초 하면 EL 10.032 기준)"}
(D / "params.json").write_text(json.dumps(P, ensure_ascii=False, indent=1), encoding="utf-8")
(D / "expected.json").write_text(json.dumps(X, ensure_ascii=False, indent=1), encoding="utf-8")
print("G2 added; backup", bk)
+56
View File
@@ -0,0 +1,56 @@
"""Add the footing rebar (G3: B1~B12, centreline polylines) to the app pier '새재1교P1'.
params = 판독/g3_bars.json (extract_g3_bars.py, Okseong rules F1-F5 applied again 2026-10-15); builder rebar_polylines.py (GATE G3)
expected = schedule L / N, drawn position lists, schedule legs b, drawn levels and the B9 rule, typed in by hand.
Backs up params.json / expected.json to data/새재1교P1/backup/2026-10-15_g3/ first. Refuses if G3 is in scope.
"""
import json
import shutil
import sys
from pathlib import Path
HERE = Path(__file__).resolve().parent
D = HERE.parents[1] / "Code" / "교각모델링앱" / "data" / "새재1교P1"
B = json.loads((HERE / "판독" / "g3_bars.json").read_text(encoding="utf-8"))
V = json.loads((HERE / "판독" / "g3_values.json").read_text(encoding="utf-8"))
P = json.loads((D / "params.json").read_text(encoding="utf-8"))
X = json.loads((D / "expected.json").read_text(encoding="utf-8"))
if "G3" in P["scope"]:
sys.exit("G3 already in scope")
bk = D / "backup" / "2026-10-15_g3"
bk.mkdir(parents=True, exist_ok=True)
for f in ("params.json", "expected.json"):
shutil.copy2(D / f, bk / f)
SCHED = {"B1": (10590, 31, "H25"), "B2": (12010, 31, "H25"), "B3": (10590, 30, "H25"), "B4": (12010, 30, "H25"),
"B5": (11190, 27, "H25"), "B6": (13210, 27, "H25"), "B7": (11190, 26, "H25"), "B8": (13210, 26, "H25"),
"B9": (6332, 45, "H19"), "B10": (32416, 4, "H19"), "B11": (7700, 11, "H19"), "B12": (7700, 23, "H19")}
SHAPE = {m: "U" for m in SCHED} | {"B9": "tie-C", "B10": "loop"}
P["scope"] = ["G1", "G2", "G3", "G5"]
P["builders"]["G3"] = "rebar_polylines.py"
P["rebar_marks"].update({m: {"dia": d, "shape": SHAPE[m]} for m, (_, _, d) in SCHED.items()})
P["footing_rebar"] = {"form": "polylines", "host": "FT", "group": "기초", "bars": B["bars"],
"not_modelled": "UM 조립용 A자형 받침 H22 L 5,496 x 80 (F5: 기록만), 겹이음 j",
"src": "Code/새재1교P1판독/extract_g3_bars.py -> 판독/g3_bars.json; 판독서 v0.1.02, 옥성교 결정 F1~F5 재적용, X방향 51곳 (R1)"}
X["checkers"]["G3"] = "g3_sj.py"
X["negative"]["G3"] = [{"mark": "B1", "d": [5, 0, 0]}, {"mark": "B10", "d": [0, 0, 5]}]
X["planned_fail"] = [{"gate": "G3", "item": f"{m} bar count vs schedule",
"reason": "작도 X방향 51곳(측면 점·사슬 '52@150=7.800 -300') 채택 vs 재료표 B5·B7 27·26, B6·B8 27·26 = 53 — OPEN #28",
"approved": "사용자 2026-10-15"} for m in ("B5", "B6", "B7", "B8")]
X["G3"] = {
"schedule": {m: [L, n] for m, (L, n, _) in SCHED.items()},
"dia": {m: int(d[1:]) for m, (_, _, d) in SCHED.items()},
"half_a": 3750,
"mats": {"y_bottom": {"marks": ["B2", "B4"], "axis": "Y", "z": 10132, "leg": 1800, "pos": V["y_bars_bottom"]["x"]},
"x_bottom": {"marks": ["B6", "B8"], "axis": "X", "z": 10154.5, "leg": 2400, "pos": V["x_bars_bottom"]["y"]},
"y_top": {"marks": ["B1", "B3"], "axis": "Y", "z": 12532, "leg": -900, "pos": V["y_bars_top"]["x"]},
"x_top": {"marks": ["B5", "B7"], "axis": "X", "z": 12509.5, "leg": -1200, "pos": V["x_bars_top"]["y"]}},
"mid": {"B12": {"axis": "Y", "lift": 19, "levels": V["mid_y_bars"]},
"B11": {"axis": "X", "lift": 0, "levels": V["mid_x_bars"]}},
"b10": {"levels": V["b10_levels"], "size": 7545},
"b9": {"rows": V["b9"]["rows"], "cols_even": V["b9"]["cols_even"], "cols_odd": V["b9"]["cols_odd"], "a": 1244, "height": 2444},
"src": "재료표 L·N·b; 정면 점 61(Y방향)·측면 점 51(X방향), 측면 EL +22.5 어긋남; 중간층 EL 10.732 / 11.332 / 11.632; B10 4단 ±3,772.5; "
"B9 정면 연직선 15곳 @500 + 측면 다리 행 6 @1,200 (짝수 행 8·홀수 행 7); F3 교번; F4 B12 Y방향 +19; 상세 a 1,244 b 2,444"}
(D / "params.json").write_text(json.dumps(P, ensure_ascii=False, indent=1), encoding="utf-8")
(D / "expected.json").write_text(json.dumps(X, ensure_ascii=False, indent=1), encoding="utf-8")
print("G3 added:", len(B["bars"]), "bars; backup", bk)
+85
View File
@@ -0,0 +1,85 @@
"""Add the coping + bearing-seat rebar (G4: C1~C20, S1~S2, centreline polylines) to the app pier '새재1교P1'.
params = 판독/g4_bars.json (extract_g4.py; Okseong rules H1-H6 applied again, 2026-10-15); builder rebar_polylines.py (GATE G4)
expected = schedule L / N, drawn levels / positions / dimension chains, typed in by hand from the reading (판독서 v0.1.03 §10).
Backs up params.json / expected.json to data/새재1교P1/backup/2026-10-15_g4/ first. Refuses if G4 is in scope.
"""
import json
import math
import shutil
import sys
from pathlib import Path
HERE = Path(__file__).resolve().parent
D = HERE.parents[1] / "Code" / "교각모델링앱" / "data" / "새재1교P1"
B = json.loads((HERE / "판독" / "g4_bars.json").read_text(encoding="utf-8"))
P = json.loads((D / "params.json").read_text(encoding="utf-8"))
X = json.loads((D / "expected.json").read_text(encoding="utf-8"))
if "G4" in P["scope"]:
sys.exit("G4 already in scope")
bk = D / "backup" / "2026-10-15_g4"
bk.mkdir(parents=True, exist_ok=True)
for f in ("params.json", "expected.json"):
shutil.copy2(D / f, bk / f)
TABLE = { # mark: (dia, L mm, N) -- 구조도(3)(4) 재료표
"C1": ("H29", 15233, 12), "C4": ("H29", 15233, 11), "C2": ("H29", 13260, 12), "C3": ("H29", 13260, 12), "C5": ("H29", 13260, 11),
"C6": ("H29", 13260, 11), "C7": ("H29", 14292, 12), "C8": ("H25", 8388, 74), "C9": ("H25", 11016, 74), "C10": ("H25", 10261, 38),
"C11": ("H25", 10196, 38), "C12": ("H25", 8915, 76), "C13": ("H25", 9056, 76), "C14": ("H22", 21269, 7), "C15": ("H22", 7434, 42),
"C16": ("H22", 31302, 4), "C17": ("H22", 13001, 24), "C18": ("H19", 3490, 92), "C19": ("H19", 2692, 23), "C20": ("H19", 3122, 69),
"S1": ("H13", 3697, 55), "S2": ("H13", 2600, 100)}
SHAPE = {"C1": "top-legs", "C2": "top-legs", "C3": "top-legs", "C4": "top-legs", "C5": "top-legs", "C6": "top-legs", "C7": "soffit",
"C8": "stirrup", "C9": "stirrup-pent", "C10": "stirrup", "C11": "stirrup-pent", "C12": "stirrup", "C13": "stirrup-pent",
"C14": "loop", "C15": "tie", "C16": "loop", "C17": "tie", "C18": "U", "C19": "U", "C20": "L", "S1": "U", "S2": "U"}
P["scope"] = ["G1", "G2", "G3", "G4", "G5"]
P["builders"]["G4"] = "rebar_polylines.py"
P["rebar_marks"].update({m: {"dia": d, "shape": SHAPE[m]} for m, (d, _, _) in TABLE.items()})
P["coping_rebar"] = {"form": "polylines", "host": "CP", "group": "코핑", "bars": B["bars"],
"not_modelled": "135도 갈고리 C15·C17, 겹이음 j(C1~C7·C14·C16·C17), 스터럽 이음 c 630",
"src": "Code/새재1교P1판독/extract_g4.py -> 판독/g4_bars.json; 판독서 v0.1.03 §10, 옥성교 H1~H6 규칙 재적용 (2026-10-15)"}
X["checkers"]["G4"] = "g4_sj.py"
X["negative"]["G4"] = [{"mark": "C1", "d": [0, 5, 0]}, {"mark": "C7", "d": [0, 0, 5]}]
def y_out(z):
return min(1375.0, 971.6 + 0.235294 * (z - 29532.0))
Y23 = [-1375.0 + 125 * k for k in range(23)]
X["G4"] = {
"schedule": {m: [L, n] for m, (_, L, n) in TABLE.items()},
"dia": {m: int(d[1:]) for m, (d, _, _) in TABLE.items()},
# polyline length = drawn a + legs (L minus lap j for C1~C6); other marks vary with x / level and are only recorded
"fixed_length": {"C1": 13924, "C4": 13924, "C2": 11950, "C3": 11950, "C5": 11950, "C6": 11950, "C19": 2691.8, "C20": 3122,
"S1": 3697, "S2": 2600},
"y23": Y23,
"top": {"C1": {"z": 32407.0, "leg": 1087, "parity": 0}, "C4": {"z": 32407.0, "leg": 1087, "parity": 1},
"C2": {"z": 32332.0, "leg": 100, "parity": 0}, "C5": {"z": 32332.0, "leg": 100, "parity": 1},
"C3": {"z": 32232.0, "leg": 100, "parity": 0}, "C6": {"z": 32232.0, "leg": 100, "parity": 1}, "x_end": 5875},
"c19": {"z": 32811.1, "x": [3923.2, 5875.0], "leg": 370},
"c20": [{"z": 32508.0, "x": [-3597.6, -845.6]}, {"z": 32609.0, "x": [-1090.6, 1661.3]}, {"z": 32710.1, "x": [1416.3, 4168.2]}],
"c20_leg": 370,
"c7": {"flat_z": [29657.0] * 8 + [30184.0] * 2 + [31246.5] * 2, "x_end": 5875, "top_end_z": 31845.3, "raised_top_z": 32372.3,
"cap_z": 32400.0},
"stirrups": {"x": [-5788.0 + 125 * k for k in range(94)], "zone_cut": [-1200.0, 1200.0],
"marks": {"left": ["C8", "C9"], "centre": ["C10", "C11"], "right": ["C12", "C13"]},
"off": {"R": [-12.5, 12.5], "P": [-37.5, 37.5]},
"step_b": [-3600.5, -1100.5, 1399.5, 3899.5], "step_z": [32531.5, 32632.5, 32733.5, 32834.5, 32936.0],
"top_below": 102.0, "flat_bottom": 29634.5, "cover_n": 102.5, "soffit_slope": 1700.0 / 4800.0, "flat_half": 1200.0,
"rect_y": [[-875.0, 625.0], [-625.0, 875.0]], "pent_in": 375.0, "pent_out": 1375.0},
"loops": {"upper": {"marks": ["C16", "C17"], "z": [32182.0, 31932.0, 31682.0, 31432.0], "x": [5875.0] * 4, "y": [1352.5] * 4},
"lower": {"marks": ["C14", "C15"], "z": [31182.0, 30932.0, 30682.0, 30432.0, 30182.0, 29932.0, 29682.0],
"x": [5484.4, 4778.6, 4072.7, 3366.8, 2660.9, 1955.0, 1249.1],
"y": [1337.3, 1278.5, 1219.6, 1160.8, 1102.0, 1043.2, 984.3]},
"tie_y": [-852.5, -602.5, -352.5, 352.5, 602.5, 852.5]},
"c18": {"levels": {"32457.0": 10, "32432.0": 10, "32309.5": 25, "32209.5": 25, "31682.0": 12, "30682.0": 8, "29682.0": 2},
"width": {"32457.0": 2750, "32432.0": 2750, "32309.5": 2750, "32209.5": 2750, "31682.0": 2 * round(y_out(32052.0), 1),
"30682.0": 2 * round(y_out(31052.0), 1), "29682.0": 2 * round(y_out(30052.0), 1)}},
"seats": {"s1_t": [-600.0] + [-500.0 + 125 * k for k in range(9)] + [600.0], "s1_len": 2297,
"s2_o": [-1148.5] + [-1062.5 + 125 * k for k in range(18)] + [1148.5], "s2_len": 1200, "top_below": 50, "leg": 700},
"src": "재료표 L·N, 철근 상세 a·b·c; 구조도(1) 정면·측면 철근 선·점(상면 3단·C19·C20·C7·스터럽 94곳·측면 고리 11단·C18 92점); "
"구조도(2) 코핑 단면 사슬·교좌면 보강 상세; 옥성교 H1~H6 규칙 재적용 [추론] (2026-10-15)",
}
(D / "params.json").write_text(json.dumps(P, ensure_ascii=False, indent=1), encoding="utf-8")
(D / "expected.json").write_text(json.dumps(X, ensure_ascii=False, indent=1), encoding="utf-8")
print("G4 added:", len(B["bars"]), "bars; backup", bk)
+20
View File
@@ -0,0 +1,20 @@
"""Saejae 1 P1: convert a copy of RAG/새재1교P1.dwg to DXF (Code/새재1교P1판독/dxf) and index texts.
Uses the app reader (sources are copied before conversion and never touched). Labels D1..D4 by file order."""
import json
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT / "Code" / "교각모델링앱"))
from engine import reader # noqa: E402
OUT = Path(__file__).resolve().parent / "dxf"
dwgs = sorted((ROOT / "RAG").glob("새재1교P1.dwg"))
audit = reader.convert(dwgs, OUT)
labels = [f"D{i}" for i in range(1, len(audit) + 1)]
for a, lab in zip(audit, labels):
a["label"] = lab
(OUT / "audit.json").write_text(json.dumps(audit, ensure_ascii=False, indent=1), encoding="utf-8")
texts = reader.build_index([OUT / a["dxf"] for a in audit], labels, OUT / "texts.json")
print(json.dumps(audit, ensure_ascii=False, indent=1))
print("texts", len(texts))
+10
View File
@@ -0,0 +1,10 @@
[
{
"source": "새재1교P1.dwg",
"source_sha256": "d1a5109698fe92427ea144a3abdf6c37843f592919598c998f90f7e9c0b6c9c6",
"dxf": "새재1교P1.dxf",
"dxf_sha256": "d10b39bcdc65ebe6178f6c351bd877deabc6cba98896a5e3bf799821f50636bf",
"engine": "ODA File Converter 27.1.0",
"label": "D1"
}
]
+1
View File
@@ -0,0 +1 @@
[{"dwg": "D1", "layer": "CZ-TEX2", "x": 34935.6, "y": 63999.8, "h": 500.0, "text": "S=1:100", "handle": "484"}, {"dwg": "D1", "layer": "CZ-TEX2", "x": 34938.7, "y": 44580.2, "h": 500.0, "text": "S=1:100", "handle": "488"}, {"dwg": "D1", "layer": "CZ-TEX2", "x": 61951.1, "y": 44513.0, "h": 500.0, "text": "S=1:100", "handle": "489"}, {"dwg": "D1", "layer": "CZ-TEX2", "x": 63108.3, "y": 63999.8, "h": 500.0, "text": "S=1:100", "handle": "48A"}, {"dwg": "D1", "layer": "CZ-TEX2", "x": 86489.9, "y": 49912.4, "h": 500.0, "text": "S=1:100", "handle": "48B"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 65612.7, "y": 50957.5, "h": 250.0, "text": "Y : 208537.27046", "handle": "491"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 60375.7, "y": 49707.5, "h": 250.0, "text": "7.700", "handle": "492"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 64992.4, "y": 50707.5, "h": 250.0, "text": "100", "handle": "493"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 62850.7, "y": 50707.5, "h": 250.0, "text": "2.750", "handle": "494"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 60375.7, "y": 50707.5, "h": 250.0, "text": "2.200", "handle": "495"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 57900.7, "y": 50707.5, "h": 250.0, "text": "2.750", "handle": "496"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 56217.4, "y": 50707.5, "h": 250.0, "text": "100", "handle": "497"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 53946.8, "y": 56136.4, "h": 250.0, "text": "7.700", "handle": "498"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 54846.8, "y": 60753.2, "h": 250.0, "text": "100", "handle": "499"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 54846.8, "y": 58611.4, "h": 250.0, "text": "2.750", "handle": "49A"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 54846.8, "y": 56136.4, "h": 250.0, "text": "2.200", "handle": "49B"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 54846.8, "y": 53661.4, "h": 250.0, "text": "2.750", "handle": "49C"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 54846.8, "y": 51978.2, "h": 250.0, "text": "100", "handle": "49D"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 65612.5, "y": 51307.5, "h": 250.0, "text": "X : 428107.17824", "handle": "49E"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 65612.5, "y": 62007.5, "h": 250.0, "text": "X : 428101.17451", "handle": "49F"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 53157.9, "y": 62007.5, "h": 250.0, "text": "X : 428105.99584", "handle": "4A0"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 53157.9, "y": 51307.5, "h": 250.0, "text": "X : 428111.99957", "handle": "4A1"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 53158.2, "y": 50957.5, "h": 250.0, "text": "Y : 208543.27419", "handle": "4A2"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 53158.2, "y": 61657.5, "h": 250.0, "text": "Y : 208548.09552", "handle": "4A3"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 65612.7, "y": 61657.5, "h": 250.0, "text": "Y : 208542.09178", "handle": "4A4"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 82553.3, "y": 41100.2, "h": 250.0, "text": "2.200", "handle": "4E5"}, {"dwg": "D1", "layer": "CZ-TEX1", "x": 32297.7, "y": 64999.8, "h": 700.0, "text": "평면도", "handle": "4F2"}, {"dwg": "D1", "layer": "CZ-TEX1", "x": 32300.8, "y": 45580.2, "h": 700.0, "text": "정면도", "handle": "4F5"}, {"dwg": "D1", "layer": "CZ-TEX1", "x": 59313.3, "y": 45513.0, "h": 700.0, "text": "단면도", "handle": "4F6"}, {"dwg": "D1", "layer": "CZ-TEX1", "x": 58248.4, "y": 64999.8, "h": 700.0, "text": "기초 평면도", "handle": "4F7"}, {"dwg": "D1", "layer": "CZ-TEX1", "x": 79163.9, "y": 50912.4, "h": 700.0, "text": "기둥 단면도 A-A", "handle": "4F9"}, {"dwg": "D1", "layer": "CS-SYMB", "x": 56196.8, "y": 56482.1, "h": 250.0, "text": "C", "handle": "4FD"}, {"dwg": "D1", "layer": "CS-SYMB", "x": 56316.8, "y": 56573.4, "h": 250.0, "text": "L", "handle": "4FE"}, {"dwg": "D1", "layer": "CS-SYMB", "x": 56316.8, "y": 56892.2, "h": 250.0, "text": "OF PIER", "handle": "4FF"}, {"dwg": "D1", "layer": "CS-SYMB", "x": 60861.7, "y": 54191.7, "h": 250.0, "text": "구체 fck = 27 MPa", "handle": "517"}, {"dwg": "D1", "layer": "CZ-TEX2", "x": 122010.5, "y": 60416.1, "h": 500.0, "text": "S=1:20", "handle": "2535"}, {"dwg": "D1", "layer": "CZ-TEX2", "x": 166784.9, "y": 54496.2, "h": 500.0, "text": "S=1:20", "handle": "2536"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 120791.4, "y": 56550.6, "h": 250.0, "text": "50", "handle": "2538"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 120905.1, "y": 53552.7, "h": 250.0, "text": "50", "handle": "2539"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 122535.4, "y": 59173.0, "h": 250.0, "text": "50", "handle": "253A"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 119554.7, "y": 58833.3, "h": 250.0, "text": "50", "handle": "253B"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 125715.1, "y": 53598.3, "h": 250.0, "text": "h2", "handle": "253C"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 125465.3, "y": 55789.8, "h": 250.0, "text": "B", "handle": "253D"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 125219.7, "y": 57945.1, "h": 250.0, "text": "h2", "handle": "253E"}, {"dwg": "D1", "layer": "CS-DIMT", "x": 125652.8, "y": 57235.7, "h": Line truncated
File diff suppressed because it is too large. Load diff
+100
View File
@@ -0,0 +1,100 @@
"""Reading aids for the Okseong P1 drawing (read only): render a region, dump entities of a region.
usage:
python dxftools.py render <D1..D4> x0 y0 x1 y1 <name> [px] -> 판독/<name>.png
python dxftools.py dump <D1..D4> x0 y0 x1 y1 [layer-regex] -> prints LINE/LWPOLYLINE/ARC/CIRCLE/TEXT
DXF source: Code/새재1교P1판독/dxf (converted from a copy of RAG/옥성교P1.dwg).
"""
import re
import sys
from pathlib import Path
import ezdxf
from ezdxf import bbox
HERE = Path(__file__).resolve().parent
DXF = HERE / "dxf"
_CACHE = {}
def doc(label):
if label not in _CACHE:
path = sorted(DXF.glob("*.dxf"))[int(label[1]) - 1]
_CACHE[label] = ezdxf.readfile(path)
return _CACHE[label]
def in_region(e, x0, y0, x1, y1):
try:
b = bbox.extents([e], fast=True)
except Exception:
return False
return b.has_data and b.extmax.x >= x0 and b.extmin.x <= x1 and b.extmax.y >= y0 and b.extmin.y <= y1
def entities(label, x0, y0, x1, y1, layer=None):
rx = re.compile(layer) if layer else None
for e in doc(label).modelspace():
if rx and not rx.search(e.dxf.layer):
continue
if in_region(e, x0, y0, x1, y1):
yield e
def describe(e):
t, L, h = e.dxftype(), e.dxf.layer, e.dxf.handle
r = lambda v: round(v, 1)
if t == "LINE":
s, f = e.dxf.start, e.dxf.end
return f"{h} {L} LINE ({r(s.x)},{r(s.y)})-({r(f.x)},{r(f.y)}) len {r(s.distance(f))}"
if t == "LWPOLYLINE":
pts = [(r(p[0]), r(p[1])) for p in e.get_points()]
return f"{h} {L} PLINE closed={e.closed} {pts}"
if t == "ARC":
c = e.dxf.center
return f"{h} {L} ARC c({r(c.x)},{r(c.y)}) r {r(e.dxf.radius)} {r(e.dxf.start_angle)}..{r(e.dxf.end_angle)}"
if t == "CIRCLE":
c = e.dxf.center
return f"{h} {L} CIRCLE c({r(c.x)},{r(c.y)}) r {r(e.dxf.radius)}"
if t in ("TEXT", "MTEXT"):
p = e.dxf.insert
s = e.plain_text() if t == "MTEXT" else e.dxf.text
return f"{h} {L} {t} ({r(p.x)},{r(p.y)}) '{s.strip()}'"
if t == "INSERT":
p = e.dxf.insert
return f"{h} {L} INSERT {e.dxf.name} ({r(p.x)},{r(p.y)})"
return f"{h} {L} {t}"
def render(label, x0, y0, x1, y1, name, px=2400):
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from ezdxf.addons.drawing import Frontend, RenderContext
from ezdxf.addons.drawing.config import BackgroundPolicy, ColorPolicy, Configuration
from ezdxf.addons.drawing.matplotlib import MatplotlibBackend
d = doc(label)
keep = list(entities(label, x0, y0, x1, y1))
fig = plt.figure(figsize=(px / 100, px * (y1 - y0) / (x1 - x0) / 100), dpi=100)
ax = fig.add_axes([0, 0, 1, 1])
cfg = Configuration(background_policy=BackgroundPolicy.WHITE, color_policy=ColorPolicy.BLACK)
Frontend(RenderContext(d), MatplotlibBackend(ax), config=cfg).draw_entities(keep)
ax.set_xlim(x0, x1)
ax.set_ylim(y0, y1)
ax.set_aspect("equal")
ax.axis("off")
out = HERE / "판독" / f"{name}.png"
out.parent.mkdir(exist_ok=True)
fig.savefig(out, facecolor="white")
plt.close(fig)
return out
if __name__ == "__main__":
cmd, label = sys.argv[1], sys.argv[2]
x0, y0, x1, y1 = map(float, sys.argv[3:7])
if cmd == "render":
print(render(label, x0, y0, x1, y1, sys.argv[7], int(sys.argv[8]) if len(sys.argv) > 8 else 2400))
else:
for e in entities(label, x0, y0, x1, y1, sys.argv[7] if len(sys.argv) > 7 else None):
print(describe(e))
+72
View File
@@ -0,0 +1,72 @@
"""Saejae-1 P1 shape reading (G1 + G5 positions) from the general drawing -> 판독/g1_values.json.
Datums: front / side views are broken in the column (break symbol), so two z offsets: below the break
z(mm) = drawing y - 14716.5 (footing bottom y 24748.5 = EL 10.032), above the break (coping) z = y - 5816.5
(coping bottom flat y 35348.5 = EL 29.532, top left y 38348.5 = EL 32.532). Front CL x 33756.4, side CL x 61366.4.
Plan: column centre (34904.3, 55436.6) = model origin; plan y up = model +Y (선형 진행 방향).
"""
import json
import math
from pathlib import Path
from dxftools import doc, entities
D = doc("D1")
FX, SX = 33756.4, 61366.4
ZF, ZC = -14716.5, -5816.5
PCX, PCY = 34904.3, 55436.6
out = {}
# front view coping outline (Y = 0 section), CS-CONC-MAJR lines of the coping, x 27700..39800, y 35300..38800
lines = [(e.dxf.start, e.dxf.end) for e in entities("D1", 27700, 35300, 39800, 38800, "CS-CONC-MAJR")
if e.dxftype() == "LINE" and e.dxf.start.distance(e.dxf.end) > 1000]
horiz = sorted({(round(a.y, 1), round(min(a.x, b.x), 1), round(max(a.x, b.x), 1)) for a, b in lines if abs(a.y - b.y) < 0.5 and a.y > 38000})
steps = [{"x0": round(x0 - FX, 1), "x1": round(x1 - FX, 1), "z": round(y + ZC, 1)} for y, x0, x1 in horiz]
bottom = [(a, b) for a, b in lines if abs(a.y - b.y) < 0.5 and abs(a.y - 35348.5) < 1]
slope = [(a, b) for a, b in lines if abs(a.y - b.y) > 100 and abs(a.x - b.x) > 100]
verts = sorted({(round(a.x, 1), round(min(a.y, b.y), 1), round(max(a.y, b.y), 1)) for a, b in lines if abs(a.x - b.x) < 0.5})
out["coping_front"] = {
"z_bottom": 29532.0, "bottom_flat_half": round(max(abs(a.x - FX) for a, b in bottom), 1) if bottom else None,
"tip_x": 6000.0, "z_tip": round(37048.5 + ZC, 1),
"end_left": {"x": -6000.0, "z0": round(37048.5 + ZC, 1), "z1": steps[0]["z"]},
"end_right": {"x": 6000.0, "z0": round(37048.5 + ZC, 1), "z1": steps[-1]["z"]},
"top_steps": steps, "verts": verts,
"src": "D1 정면도 코핑 외곽 2F1A~2F27 (Y = 0 단면), 치수 '1.300', '1.704', '2.277', '3@2.507', '2.202'"}
# side view: coping 3,000 wide, flat bottom 2,200, side taper to EL 31.232
out["coping_side"] = {"half_width_top": 1500.0, "z_taper_top": round(37048.5 + ZC, 1), "half_width_bottom": 1100.0,
"z_bottom": 29532.0, "src": "D1 단면도 코핑 2DAF/2DB0 (±1,100 → ±1,500, 경사 1,746.4), 폭 3,000"}
out["column"] = {"d": 2200.0, "z0": 12632.0, "z1": 29532.0,
"src": "D1 정면 기둥 2.200, 높이 16.900(치수), 평면 원 r 1,100 (29C8~29CF)"}
out["footing"] = {"size_x": 7700.0, "size_y": 7700.0, "z0": 10032.0, "z1": 12632.0,
"src": "D1 정면 2E24~2E2E (7.700 × 2.600), 기초 평면도 7.700"}
out["lean"] = {"size_x": 7900.0, "size_y": 7900.0, "z0": 9932.0, "z1": 10032.0, "src": "D1 정면 2E24~2E27 (7.900 × 100)"}
# coping plan (rectangular, 12,000 x 3,000): 28FA~28FD
out["coping_plan"] = {"x": [28904.3 - PCX, 40904.3 - PCX], "y": [53936.6 - PCY, 56936.6 - PCY],
"step_lines_x": [round(x - PCX, 1) for x in (31181.7, 33688.7, 36195.6, 38702.5)],
"src": "D1 평면 28FA~2901 (직사각, 사각 없음)"}
def rect(h):
pts = [p[:2] for p in D.entitydb[h].get_points("xy")]
cx, cy = sum(p[0] for p in pts) / 4 - PCX, sum(p[1] for p in pts) / 4 - PCY
e = [(pts[(i + 1) % 4][0] - pts[i][0], pts[(i + 1) % 4][1] - pts[i][1]) for i in range(4)]
L = [math.hypot(*v) for v in e]
ia = max(range(4), key=lambda i: abs(e[i][1]))
vx, vy = e[ia] if e[ia][1] > 0 else (-e[ia][0], -e[ia][1])
return {"centre": [round(cx, 1), round(cy, 1)], "along": round(L[ia], 1), "across": round(L[(ia + 1) % 4], 1),
"rotation_deg": round(math.degrees(math.atan2(vx, vy)), 3), "src": f"D1 평면 {h}"}
# pads (outer 750 x 750 of three nested rectangles); NO.1-5 lower row (front, y < 0) left -> right, NO.6-10 upper row
outer = {10: "2989", 9: "298C", 8: "298F", 7: "2992", 6: "2995", 5: "2998", 4: "299B", 3: "299E", 2: "29A1", 1: "29A4"}
out["pads_outer"] = {no: rect(h) for no, h in outer.items()}
# pedestals: axis-aligned rectangles 1,300 (X) x 2,397 (Y), one per bearing station (both rows)
peds = []
for x0, x1 in ((29278.3, 30578.3), (31785.2, 33085.2), (34292.2, 35592.2), (36799.1, 38099.1), (39305.9, 40605.9)):
peds.append({"x": [round(x0 - PCX, 1), round(x1 - PCX, 1)], "y": [round(54236.9 - PCY, 1), round(56633.6 - PCY, 1)],
"src": "D1 평면 대좌 28D6~28F9"})
out["pedestals"] = peds
p = Path(__file__).resolve().parent / "판독" / "g1_values.json"
p.write_text(json.dumps(out, ensure_ascii=False, indent=1), encoding="utf-8")
print(json.dumps({k: v for k, v in out.items() if k not in ("pads_outer", "pedestals")}, ensure_ascii=False)[:1800])
print({k: (v["centre"], v["along"], v["across"], v["rotation_deg"]) for k, v in out["pads_outer"].items()})
+48
View File
@@ -0,0 +1,48 @@
"""Saejae-1 P1 column rebar reading (G2: P1~P5) -> 판독/g2_values.json.
Sheet 구조도(1) front view: column CL x 225532, z = drawing y - 10329.7 (footing bottom y 20361.7 = EL 10.032, top y 22961.7).
The column is drawn broken (cut symbol), so only 42 hoop lines are drawn; the dimension chains give all levels:
'띠철근외측' 100 | 1.300 | 4@300 | 18@150 | 36@300 | 9@300 | 4@300 | 2.375 | 125 (= 22.500 from the footing bottom, 72 hoops),
'크로스타이' 100 | 950 | 600 | 7@300 | 15@600 | 14@300 | 2@600 | 4.225 | 125 (= 22.500, 40 levels).
Sheet 구조도(2) sections: bar symbols on r 975 (P1, 49) and 930 (P2, 49), hoop arcs r 997.5, ties through the centre.
"""
import json
import math
from collections import Counter
from pathlib import Path
from dxftools import entities
CX, ZO = 225532.0, -10329.7
out = {}
drawn = sorted({round(e.dxf.start.y + ZO, 1) for e in entities("D1", CX - 1500, 14000, CX + 1500, 36000, "CS-RBAR")
if e.dxftype() == "LINE" and abs(e.dxf.start.y - e.dxf.end.y) < 0.5 and abs(abs(e.dxf.start.x - e.dxf.end.x) - 1950) < 1})
out["hoops_drawn"] = {"count": len(drawn), "levels": drawn}
sec = [(268681, 23662), (260729, 23598), (290798, 33491), (283884, 33520), (276837, 33398)]
secs = []
for cx, cy in sec:
ins = [e for e in entities("D1", cx - 1300, cy - 1300, cx + 1300, cy + 1300, "CS-RBAR") if e.dxftype() == "INSERT"]
rr = Counter(round(math.hypot(e.dxf.insert.x - cx, e.dxf.insert.y - cy) / 2.5) * 2.5 for e in ins)
ang = sorted(round(math.degrees(math.atan2(e.dxf.insert.y - cy, e.dxf.insert.x - cx)) % 360, 2) for e in ins if abs(math.hypot(e.dxf.insert.x - cx, e.dxf.insert.y - cy) - 975) < 5)
secs.append({"centre": [cx, cy], "rings": {str(r): n for r, n in rr.most_common(2)}, "angle_pitch": round(360 / 49, 3),
"n_outer": len(ang)})
out["sections"] = secs
out["section_ties"] = {"x_line": [267684.3 - 268681, 269678.7 - 268681], "y_offset": 25.0, "length": 1994.4, "hoop_arc_r": 997.5}
B = 10032.0
hoops = [B + 100 + 1300]
for n, p in ((4, 300), (18, 150), (36, 300), (9, 300), (4, 300)):
hoops += [hoops[-1] + p * k for k in range(1, n + 1)]
ties = [B + 100 + 950]
ties += [ties[-1] + 600]
for n, p in ((7, 300), (15, 600), (14, 300), (2, 600)):
ties += [ties[-1] + p * k for k in range(1, n + 1)]
out["hoops_chain"], out["ties_chain"] = hoops, ties
out["hoop_zones"] = [["P3", 5], ["P4", 18], ["P3", 36], ["P4", 9], ["P3", 4]]
drawn_set = {round(z, 1) for z in drawn}
out["check"] = {"n_hoops": len(hoops), "n_tie_levels": len(ties), "hoops_end_to_coping_top": B + 22375 + 125,
"drawn_subset_of_chain": all(any(abs(d - h) < 0.6 for h in hoops) for d in drawn if d < 15500),
"drawn_beyond_break_not_on_chain": [d for d in drawn if d >= 15500 and not any(abs(d - h) < 0.6 for h in hoops)][:12]}
p = Path(__file__).resolve().parent / "판독" / "g2_values.json"
p.write_text(json.dumps(out, ensure_ascii=False, indent=1), encoding="utf-8")
print(json.dumps({k: out[k] for k in ("section_ties", "check")}, ensure_ascii=False), hoops[:3], hoops[-2:], ties[:3], ties[-2:])
print([s["rings"] for s in secs])
+37
View File
@@ -0,0 +1,37 @@
"""Saejae-1 P1 footing rebar reading (G3: B1~B12, UM) -> 판독/g3_values.json.
Sheet 구조도(1): front CL x 225817.5, side CL x 242892.5, z = drawing y - 10329.7 (footing bottom EL 10.032 at y 20361.7).
Front dots = bars along Y (positions x), side dots = bars along X (positions y). X bars sit 22.5 above / below the Y bars
(bottom 10154.5 / 10132, top 12509.5 / 12532). Chains: front '100 | 2@75 | 60@125 = 7.500 | -300 | 2@75 | 100', side '52@150 = 7.800 -300'.
Plan (구조도(3)): B9 symbols (EREC) lower rows only; rows y -2850 + 1200 k (side legs at row -+ 600), columns from the front chain
'15@500 = 7.500' x -3600 + 500 j (even rows 8, odd rows 7 -> 45).
"""
import json
from pathlib import Path
from dxftools import entities
FX, SX, ZO = 225817.5, 242892.5, -10329.7
def dots(cx, z, lim=3800):
return sorted(round(e.dxf.insert.x - cx, 1) for e in entities("D1", cx - 4200, z - ZO - 5, cx + 4200, z - ZO + 5, "CS-RBAR")
if e.dxftype() == "INSERT" and abs(e.dxf.insert.x - cx) <= lim)
out = {"y_bars_bottom": {"z": 10132.0, "x": dots(FX, 10132.0)}, "y_bars_top": {"z": 12532.0, "x": dots(FX, 12532.0)},
"x_bars_bottom": {"z": 10154.5, "y": dots(SX, 10154.5)}, "x_bars_top": {"z": 12509.5, "y": dots(SX, 12509.5)}}
mid_y, mid_x = {}, {}
for z in (10732.0, 11332.0, 11632.0):
mid_y[str(int(z))] = [x for x in dots(FX, z) if abs(x) < 3700]
mid_x[str(int(z))] = [y for y in dots(SX, z) if abs(y) < 3770 or abs(y) == 3750.0]
out["mid_y_bars"], out["mid_x_bars"] = mid_y, mid_x
out["b10_levels"] = [z for z in (10432.0, 10732.0, 11332.0, 11632.0) if 3772.5 in dots(FX, z, 3800)]
out["b10_corner"] = 3772.5
out["b9"] = {"cols_even": [-3600.0 + 1000 * j for j in range(8)], "cols_odd": [-3100.0 + 1000 * j for j in range(7)],
"rows": [-2850.0 + 1200 * k for k in range(6)], "a": 1244.0, "b": 2444.0, "c": 100.0, "zt": 12554.0, "zb": 10110.0}
out["counts"] = {k: len(v["x"] if "x" in v else v["y"]) for k, v in out.items() if k.endswith(("bottom", "top")) and isinstance(v, dict) and k != "b9"}
p = Path(__file__).resolve().parent / "판독" / "g3_values.json"
p.write_text(json.dumps(out, ensure_ascii=False, indent=1), encoding="utf-8")
print(out["counts"], {k: len(v) for k, v in mid_y.items()}, {k: len(v) for k, v in mid_x.items()}, out["b10_levels"])
print("mid_x", mid_x)
@@ -0,0 +1,65 @@
"""Saejae-1 P1 footing rebar (G3: B1~B12) -> centreline polylines for the generic builder rebar_polylines.py (GATE G3).
Same rules as Okseong P1 (decisions F1-F5 applied again 2026-10-15): mats U-bars with two marks alternating along the sorted positions,
X bars 22.5 beside the Y bars, B12 (Y mid bars) lifted 19, B9 'ㄷ' ties from the drawn grid rule, UM not modelled, laps not modelled.
Inputs: 판독/g3_values.json. Output: 판독/g3_bars.json. Model axes: X along the coping, Y across, Z = EL x 1000, footing centre = origin.
"""
import json
from pathlib import Path
HERE = Path(__file__).resolve().parent
V = json.loads((HERE / "판독" / "g3_values.json").read_text(encoding="utf-8"))
bars = []
H = 3750.0 # a 7,500 / 2
def rb(d):
return ((2 * d if d <= 16 else 3.5 * d) + d) / 2
def add(mark, occ, pts, dia, L, src, r=None):
bars.append({"mark": mark, "occ": occ, "pts": [[round(v, 2) for v in p] for p in pts], "r": rb(dia) if r is None else r,
"design_length": L, "src": src})
def u_y(x, z, leg):
return [(x, -H, z + leg), (x, -H, z), (x, H, z), (x, H, z + leg)]
def u_x(y, z, leg):
return [(-H, y, z + leg), (-H, y, z), (H, y, z), (H, y, z + leg)]
for key, marks, axis, leg, L, src in (
("y_bars_bottom", ("B2", "B4"), "Y", 1800, 12010, "정면 하면 점 EL 10.132, 측면 다리 1,800"),
("x_bars_bottom", ("B6", "B8"), "X", 2400, 13210, "측면 하면 점 EL 10.1545, 정면 다리 2,400"),
("y_bars_top", ("B1", "B3"), "Y", -900, 10590, "정면 상면 점 EL 12.532, 측면 다리 900"),
("x_bars_top", ("B5", "B7"), "X", -1200, 11190, "측면 상면 점 EL 12.5095, 정면 다리 1,200")):
z = V[key]["z"]
pos = V[key]["x"] if axis == "Y" else V[key]["y"]
for i, v in enumerate(pos):
add(marks[i % 2], f"{axis.lower()}{v:+.1f}", u_y(v, z, leg) if axis == "Y" else u_x(v, z, leg), 25, L,
src + f"; {marks[0]}/{marks[1]} 교번, 겹이음 j 미모델 (F3 [추론])")
for zs, xs in V["mid_y_bars"].items():
for x in xs:
add("B12", f"z{zs}x{x:+.0f}", u_y(x, float(zs) + 19, -100), 19, 7700, f"정면 중간 점 EL {float(zs) / 1000:.3f} (+19, F4 [추론])")
for zs, ys in V["mid_x_bars"].items():
for y in ys:
add("B11", f"z{zs}y{y:+.0f}", u_x(y, float(zs), -100), 19, 7700, f"측면 중간 점 EL {float(zs) / 1000:.3f} (F4 [추론])")
c = V["b10_corner"]
for zs in V["b10_levels"]:
add("B10", f"z{zs:.0f}", [(-c, 0, zs), (-c, -c, zs), (c, -c, zs), (c, c, zs), (-c, c, zs), (-c, 0, zs)], 19, 32416,
"정면·측면 모서리 점 ±3,772.5, 재료표 7,544 x 7,544, 겹이음 560 x 4 미모델")
b9 = V["b9"]
for k, y in enumerate(b9["rows"]):
for x in (b9["cols_even"] if k % 2 == 0 else b9["cols_odd"]):
a2, cc, zt, zb = b9["a"] / 2, b9["c"], b9["zt"], b9["zb"]
add("B9", f"x{x:+.0f}y{y:+.0f}", [(x, y - a2 + cc, zb), (x, y - a2, zb), (x, y - a2, zt), (x, y + a2, zt), (x, y + a2, zb),
(x, y + a2 - cc, zb)], 19, 6332,
"정면 연직선 15곳 @500(짝수 행 8·홀수 행 7), 측면 다리 행 6 @1,200; 상세 a 1,244 b 2,444 c 100 [행·열 규칙, F1/F2형 추론]")
count = {}
for b in bars:
count[b["mark"]] = count.get(b["mark"], 0) + 1
out = {"bars": bars, "summary": {"bars": len(bars), "per_mark": count}}
(HERE / "판독" / "g3_bars.json").write_text(json.dumps(out, ensure_ascii=False), encoding="utf-8")
print(json.dumps(out["summary"], ensure_ascii=False))
+175
View File
@@ -0,0 +1,175 @@
"""Saejae-1 P1 coping + bearing-seat rebar (G4: C1~C20, S1~S2) -> centreline polylines for the generic builder rebar_polylines.py.
Inputs: the drawing (DXF 구조도(1) front: stirrup stations, side-loop lines, C18 / C19 / C20 / C7 lines and points; 구조도(2) sections A-A / B-B:
stirrup polygons, loop / tie y), the schedule, params.json (pedestals), the Okseong rules (H1-H6 style) applied again 2026-10-15.
Output: 판독/g4_bars.json {"bars": [...], "summary": {...}} used by add_g4.py. Model axes: X along the coping, Y across, Z = EL x 1000, pier centre
at the origin; the plan is rectangular (no shear).
Front datum: z = drawing y - 1,429.7 (coping part), centre x 225,817.5.
"""
import json
import math
from collections import defaultdict
from pathlib import Path
from dxftools import entities
HERE = Path(__file__).resolve().parent
APP = HERE.parents[1] / "Code" / "교각모델링앱"
P = json.loads((APP / "data" / "새재1교P1" / "params.json").read_text(encoding="utf-8"))
SCH = {m: float(v) for m, v in json.loads((HERE / "판독" / "g4_schedule.json").read_text(encoding="utf-8")).items()} if (HERE / "판독" / "g4_schedule.json").exists() else {}
FX, ZO = 225817.5, -1429.7
bars = []
STEP_B = [-3722.6, -1215.6, 1291.3, 3798.2]
STEP_Z = [32531.5, 32632.5, 32733.5, 32834.5, 32936.0]
TAN_S = 1700.0 / 4800.0 # soffit slope
COS_S = 4800.0 / math.hypot(4800.0, 1700.0)
KF = 400.0 / 1700.0 # side taper (half width 1,100 -> 1,500)
Y23 = [-1375.0 + 125 * k for k in range(23)]
def rb(dia):
return ((2 * dia if dia <= 16 else 3.5 * dia) + dia) / 2
DIA = {"C1": 29, "C2": 29, "C3": 29, "C4": 29, "C5": 29, "C6": 29, "C7": 29, "C8": 25, "C9": 25, "C10": 25, "C11": 25, "C12": 25,
"C13": 25, "C14": 22, "C15": 22, "C16": 22, "C17": 22, "C18": 19, "C19": 19, "C20": 19, "S1": 13, "S2": 13}
def add(mark, occ, pts, src, r=None):
length = sum(math.dist(a, b) for a, b in zip(pts, pts[1:]))
bars.append({"mark": mark, "occ": occ, "pts": [[round(v, 2) for v in p] for p in pts], "r": rb(DIA[mark]) if r is None else r,
"design_length": round(length, 1), "src": src})
def step_z(x):
return STEP_Z[sum(1 for b in STEP_B if x >= b)]
TIER_B = [-3600.5, -1100.5, 1399.5, 3899.5] # drawn stirrup top tiers (stations; between 2 stations, not at the step edges)
def tier_z(x):
return STEP_Z[sum(1 for b in TIER_B if x >= b)]
def soffit(x):
return 29532.0 if abs(x) <= 1200 else 29532.0 + TAN_S * (abs(x) - 1200)
def y_out(z): # stirrup / loop outer line: 128.4 inside the side taper face
return min(1375.0, 971.6 + 0.235294 * (z - 29532.0))
# ---- C1~C6 top bars: 3 layers, 23 rows, marks alternate, x +-5,875 -------------------------------------------------------------
for z, legs, (ma, mb) in ((32407.0, 1087.0, ("C1", "C4")), (32332.0, 100.0, ("C2", "C5")), (32232.0, 100.0, ("C3", "C6"))):
for i, y in enumerate(Y23):
add((ma, mb)[i % 2], f"y{y:+.0f}", [(-5875, y, z - legs), (-5875, y, z), (5875, y, z), (5875, y, z - legs)],
f"정면 선 EL {z / 1000:.3f}, x ±5,875, 다리 {legs:.0f}; 단면 사슬 23줄 @125, 교번 [추론 F3형], 겹이음 j 미모델")
# ---- C19 / C20: stepped top pieces, 23 rows -----------------------------------------------------------------------------------
PIECES = [("C20", 32508.0, -3597.6, -845.6, "left"), ("C20", 32609.0, -1090.6, 1661.3, "left"), ("C20", 32710.1, 1416.3, 4168.2, "left"),
("C19", 32811.1, 3923.2, 5875.0, "both")]
for mark, z, xa, xb, leg in PIECES:
for y in Y23:
if leg == "both":
p = [(xa, y, z - 370), (xa, y, z), (xb, y, z), (xb, y, z - 370)]
else:
p = [(xa, y, z - 370), (xa, y, z), (xb, y, z)]
add(mark, f"x{xa:+.0f}y{y:+.0f}", p, f"정면 선 EL {z / 1000:.4f}, x {xa} ~ {xb}, 다리 370 (단 상면 − 125)")
# ---- C7: soffit bar ('a' 525 up, slope, flat); 8 bars flat, 2 + 2 raised along the side face (as Okseong H3) ---------------------
SLOPE = (31320.3 - 29657.0) / (5875.0 - 1178.5)
CAP = 32400.0
for y in [-1375.0 + 250 * k for k in range(12)]:
dz = 0.0 if abs(y) <= 875 else (30184.0 - 29657.0 if abs(y) <= 1125 else 31246.5 - 29657.0)
zr, top = 31320.3 + dz, 31320.3 + 525 + dz
if top > CAP:
xe = 1178.5 + (CAP - (29657.0 + dz)) / SLOPE
pts = [(-xe, y, CAP), (-1178.5, y, 29657.0 + dz), (1178.5, y, 29657.0 + dz), (xe, y, CAP)]
else:
pts = [(-5875, y, top), (-5875, y, zr), (-1178.5, y, 29657.0 + dz), (1178.5, y, 29657.0 + dz), (5875, y, zr), (5875, y, top)]
add("C7", f"y{y:+.0f}", pts, "정면 하면 경사선(±1,178.5 평평 EL 29.657, ±5,875 EL 31.3203, 위 끝 연직 525), 단면 B-B 점 EL 29.657 / 30.184 / 31.2465")
# ---- stirrups C8~C13: 94 stations x = -5788 + 125 k; per station 2 rectangles (C8/C10/C12) + 2 pentagons (C9/C11/C13) -------------
ST = [-5788.0 + 125 * k for k in range(94)]
OFF = {"PL": -37.5, "R1": -12.5, "R2": 12.5, "PR": 37.5}
def zone(x):
return 0 if x < -1200 else (1 if x <= 1200 else 2)
for x in ST:
zt = tier_z(x) - 102.0 # drawn line = pad - 124.5, 22.5 drawn offset -> centre pad - 102
def zb_at(xb):
return soffit(xb) + 102.5 / (1.0 if abs(xb) <= 1200 else COS_S)
rect, pent = (("C8", "C9"), ("C10", "C11"), ("C12", "C13"))[zone(x)]
for tag, (y0, y1) in (("R1", (-875.0, 625.0)), ("R2", (-625.0, 875.0))):
xx = x + OFF[tag]
zb = zb_at(xx)
add(rect, f"x{x:+.0f}{tag}", [(xx, (y0 + y1) / 2, zt), (xx, y1, zt), (xx, y1, zb), (xx, y0, zb), (xx, y0, zt), (xx, (y0 + y1) / 2, zt)],
f"정면 연직선 x {x}, 단면 A-A/B-B 직사각 y {y0:.0f} ~ {y1:.0f}, 위 = 단 상면 − 102, 아래 = 하면 + 102.5 [x 어긋남 {OFF[tag]:+.1f}, 추론]")
for tag, s in (("PL", -1), ("PR", 1)):
xx = x + OFF[tag]
zb = zb_at(xx)
yb = y_out(zb)
zc = 29532.0 + (1375.0 - 971.6) / 0.235294
yin = -s * 375.0
p = [(xx, s * 500.0, zt), (xx, s * 1375.0, zt)]
if zb < zc - 20:
p += [(xx, s * 1375.0, zc)]
p += [(xx, s * yb, zb)]
else:
p += [(xx, s * 1375.0, zb)]
p += [(xx, yin, zb), (xx, yin, zt), (xx, s * 500.0, zt)]
add(pent, f"x{x:+.0f}{tag}", p, f"단면 B-B 5각형: 안쪽 y {yin:+.0f}, 바깥 ±1,375 → 측면 테이퍼 따라 모따기, [x 어긋남 {OFF[tag]:+.1f}, 추론]")
# ---- side loops C16 (upper 4) / C14 (lower 7) and ties C17 / C15 (6 rows: y +-352.5, +-602.5, +-852.5) -------------------------------
D_H = {}
for e in entities("D1", FX - 6600, 30800, FX + 6600, 34300, "CS-RBAR"):
if e.dxftype() == "LINE" and abs(e.dxf.start.y - e.dxf.end.y) < 0.5:
z = round(e.dxf.start.y + ZO, 1)
D_H[z] = max(D_H.get(z, 0), round(max(abs(e.dxf.start.x - FX), abs(e.dxf.end.x - FX)), 1))
UP = [32182.0, 31932.0, 31682.0, 31432.0]
LOW = [31182.0, 30932.0, 30682.0, 30432.0, 30182.0, 29932.0, 29682.0]
for levels, loop, tie in ((UP, "C16", "C17"), (LOW, "C14", "C15")):
for z in levels:
xe = D_H[z]
yo = 1352.5 if z >= 31400 else y_out(z) - 0.0
if z < 31400:
yo = round(1337.3 - (31182.0 - z) * 0.2354, 1) # drawn dots ±1337.3 ... ±984.3 (taper)
add(loop, f"z{z:.0f}", [(0, yo, z), (xe, yo, z), (xe, -yo, z), (-xe, -yo, z), (-xe, yo, z), (0, yo, z)],
f"정면 선 EL {z / 1000:.3f} x ±{xe}, 단면 B-B 점 y ±{yo}")
for y in (-852.5, -602.5, -352.5, 352.5, 602.5, 852.5):
add(tie, f"z{z:.0f}y{y:+.1f}", [(-xe, y, z), (xe, y, z)], f"정면 선 EL {z / 1000:.3f}, 단면 점 y {y} (135° 갈고리 미모델)")
# ---- C18: Y-direction U at every drawn front point (7 levels, 92) ------------------------------------------------------------------
dots = defaultdict(list)
for e in entities("D1", FX - 6600, 30800, FX + 6600, 34300, "CS-RBAR"):
if e.dxftype() == "INSERT":
dots[round(e.dxf.insert.y + ZO, 1)].append(round(e.dxf.insert.x - FX, 1))
C18_Z = [32457.0, 32432.0, 32309.5, 32209.5, 31682.0, 30682.0, 29682.0]
for z in C18_Z:
hl = y_out(z)
for x in sorted(dots[z]):
if z >= 32000:
p = [(x, -hl, z - 370), (x, -hl, z), (x, hl, z), (x, hl, z - 370)]
else:
yl = y_out(z + 370)
p = [(x, -yl, z + 370), (x, -hl, z), (x, hl, z), (x, yl, z + 370)]
add("C18", f"x{x:+.0f}z{z:.0f}", p, f"정면 점 EL {z / 1000:.4f}, 측면 폭 ±{hl:.1f}, 다리 370 (낮은 단은 위로, 옥성교 H3 규칙)")
# ---- seat bars per pedestal: S1 (11, a 2,297 along Y), S2 (20, a 1,200 along X), legs 700 down -------------------------------------
for k, ped in enumerate(P["bearing_seats"]["pedestals"]):
xs = [c[0] for c in ped["corners"]]
ys = [c[1] for c in ped["corners"]]
cx, cy = (min(xs) + max(xs)) / 2, (min(ys) + max(ys)) / 2
zp = (ped["top"]["z0"] + ped["top"]["z1"]) / 2
z1, z2 = zp - 50, zp - 50 - 13
for j, dx in enumerate([-600.0] + [-500.0 + 125 * i for i in range(9)] + [600.0]):
add("S1", f"P{k + 1}-{j:02d}", [(cx + dx, cy - 1148.5, z1 - 700), (cx + dx, cy - 1148.5, z1), (cx + dx, cy + 1148.5, z1), (cx + dx, cy + 1148.5, z1 - 700)],
f"교좌면 보강 상세, 대좌 {k + 1}, S1 11 × 대좌 [추론 방향]", r=rb(13))
for j, dy in enumerate([-1148.5] + [-1062.5 + 125 * i for i in range(18)] + [1148.5]):
add("S2", f"P{k + 1}-{j:02d}", [(cx - 600, cy + dy, z2 - 700), (cx - 600, cy + dy, z2), (cx + 600, cy + dy, z2), (cx + 600, cy + dy, z2 - 700)],
f"교좌면 보강 상세, 대좌 {k + 1}, S2 20 × 대좌 [추론 방향]", r=rb(13))
count = {}
for b in bars:
count[b["mark"]] = count.get(b["mark"], 0) + 1
out = {"bars": bars, "summary": {"bars": len(bars), "per_mark": count}}
(HERE / "판독" / "g4_bars.json").write_text(json.dumps(out, ensure_ascii=False), encoding="utf-8")
print(json.dumps(out["summary"], ensure_ascii=False))
+134
View File
@@ -0,0 +1,134 @@
"""Create the app pier '새재1교P1' (tapered T on a spread footing, shared pedestals, rectangular plan; scope G1 + G5) through
the web client: new pier (Ulsan template as a starting copy), upload a copy of RAG/새재1교P1.dwg, then write params / expected
from the reading (판독/g1_values.json; DOC/02_분석/분석_새재1교P1교각도면판독_2026-10-15_v0.1.00.md) and decisions N1-N3.
usage: python make_pier.py (refuses if the pier already exists)
"""
import json
import sys
from io import BytesIO
from pathlib import Path
HERE = Path(__file__).resolve().parent
ROOT = HERE.parents[1]
APP = ROOT / "Code" / "교각모델링앱"
sys.path.insert(0, str(APP / "web"))
import app as webapp # noqa: E402
import store # noqa: E402
NAME = "새재1교P1"
V = json.loads((HERE / "판독" / "g1_values.json").read_text(encoding="utf-8"))
cf = V["coping_front"]
# the five top steps (drawing lines 2F1F..2F27: y 38348.5 + 101 x k; z = y - 5816.5); bounds = bearing-line step edges
# step z = EL.'X' - h1 - h2 of the ELEVATION TABLE: the front row gives 32531 / 32632 / 32733 / 32834 / 32936, the rear row
# 32532 / 32633 / 32734 / 32835 / 32936 (rows differ by 1 mm = table rounding; drawing lines 32532.0 / 32633.1 / ...).
# The model uses the mean (x.5) so that both rows stay within 0.5 mm of the table.
STEPS = [{"x0": -6000.0, "x1": -3722.5, "z": 32531.5}, {"x0": -3722.5, "x1": -1215.6, "z": 32632.5},
{"x0": -1215.6, "x1": 1291.3, "z": 32733.5}, {"x0": 1291.3, "x1": 3798.2, "z": 32834.5},
{"x0": 3798.2, "x1": 6000.0, "z": 32936.0}]
FLAT, TIP, ZB, ZTIP = 1200.0, 6000.0, 29532.0, 31232.0
prof = [(-FLAT, ZB), (FLAT, ZB), (TIP, ZTIP)]
for s in reversed(STEPS):
prof += [(s["x1"], s["z"]), (s["x0"], s["z"])]
prof += [(-TIP, ZTIP)]
TABLE = {1: (32790, 209), 2: (32891, 209), 3: (32992, 209), 4: (33093, 209), 5: (33194, 208),
6: (32776, 194), 7: (32877, 194), 8: (32978, 194), 9: (33079, 194), 10: (33180, 194)}
SOLE = {1: (-0.460, 23, 24, 22), 2: (-0.458, 23, 24, 22), 3: (-0.456, 23, 24, 22), 4: (-0.454, 23, 24, 22), 5: (-0.452, 23, 24, 22),
6: (-0.504, 24, 26, 22), 7: (-0.502, 24, 26, 22), 8: (-0.500, 24, 26, 22), 9: (-0.498, 24, 26, 22), 10: (-0.496, 24, 26, 22)}
pads = {int(k): v for k, v in V["pads_outer"].items()}
step_z = lambda no: STEPS[(no - 1) % 5]["z"] # NO.1-5 front row / 6-10 rear row lie on step 1..5 (left -> right)
YF = pads[1]["centre"][1] # front (lower) pad row y
YR = pads[6]["centre"][1] # rear (upper) pad row y
pedestals = []
for i, pd in enumerate(V["pedestals"]):
x0, x1 = pd["x"]
ya, yb = pd["y"]
zs = step_z(i + 1)
pedestals.append({"no": i + 1, "corners": [[x1, ya], [x0, ya], [x0, yb], [x1, yb]], "z_bottom": zs,
"top": {"y0": YF, "z0": zs + TABLE[i + 1][1], "y1": YR, "z1": zs + TABLE[i + 6][1]},
"src": pd["src"] + "; 상면 앞 + h1 → 뒤 + h1 평면 경사 (N2 [추론])"})
bearings = [{"no": no, "type": "받침", "row": "front" if no <= 5 else "rear", "centre": pads[no]["centre"],
"rotation_deg": pads[no]["rotation_deg"], "seat_z": step_z(no), "el_x": TABLE[no][0], "h1": TABLE[no][1],
"h2": 50, "A": 550, "B": 550, "pedestal": (no - 1) % 5} for no in range(1, 11)]
params = {
"_schema": "pier-T/1", "pier_id": "P1",
"_meta": {"structure": "새재1교 P1 교각 (T형, 직접기초, 직선 경사 코핑, 평면 직사각, 받침 10개·대좌 5개 공유)",
"status": "형상(G1)·받침(G5) 판독 2026-10-15, 결정 N1~N3 사용자 확정. 철근 G2~G4 미판독(이번 범위 밖)",
"units": "mm; Z = EL x 1000", "frame": "X 코핑 길이 방향, Y 평면 위쪽(선형 진행 방향), 원점 = 기둥 중심",
"sources": {"D1": "RAG/새재1교P1.dwg (교각 일반도(1)(2) + 구조도(1)~(4))"},
"reading": "DOC/02_분석/분석_새재1교P1교각도면판독_2026-10-15_v0.1.00.md, Code/새재1교P1판독/판독/g1_values.json"},
"scope": ["G1", "G5"], "builders": {"G1": "concrete_tapered.py"},
"lean_concrete": {"size_x": 7900.0, "size_y": 7900.0, "z_bottom": 9932.0, "z_top": 10032.0, "src": V["lean"]["src"]},
"footing": {"size_x": 7700.0, "size_y": 7700.0, "z_bottom": 10032.0, "thickness": 2600.0, "src": V["footing"]["src"]},
"column": {"shape": "circular", "diameter": 2200.0, "height": 16900.0, "src": V["column"]["src"]},
"coping": {"form": "tapered", "profile_xz": [list(p) for p in prof], "width_y": 3000.0, "plan_length": 12000.0,
"top_length": 12000.0, "z_tip": ZTIP, "z_top_left": STEPS[0]["z"], "z_top_right": STEPS[-1]["z"],
"plan_corner_radius": 0,
"side_taper": {"half_width_top": 1500.0, "z_taper_top": ZTIP, "half_width_bottom": 1100.0},
"skew_deg": 0.0,
"src": {"profile": cf["src"] + " (Y = 0 단면, 상면 5단)", "side": V["coping_side"]["src"],
"plan": V["coping_plan"]["src"]}},
"materials": {"fck": {"lean": "16MPa", "footing": "27MPa", "column": "35MPa", "coping": "35MPa", "seat": "35MPa"},
"src": "일반도 주기 '버림 CON'C fck = 16 MPa', '구체 fck = 27 MPa'(기초), '구체 fck = 35 MPa'(코핑); 기둥·대좌 35 [추론] (N3)"},
"bearing_seats": {"_note": "shared pedestals (one per bearing station, both rows), sloped top (N2); pads rotated per bearing",
"pad_margin_bottom": 200, "pad_margin_top": 100, "pedestals": pedestals, "bearings": bearings,
"src": "일반도(1) 평면 대좌 28D6~28F9, 패드 2989~29A6; ELEVATION TABLE h1·h2·A·B"},
"sole_plates": {"table": [{"no": no, "S": SOLE[no][0], "L": 650, "W": 650, "T": SOLE[no][1], "T1": SOLE[no][2], "T2": SOLE[no][3]}
for no in range(1, 11)],
"h3": 132, "bearing_size": "AB", "bearing_shrink": 100,
"colours": {"bearing": [0, 0, 0], "sole_plate": [150, 150, 150]},
"sole_plate_src": "솔플레이트 상세 TABLE; S < 0 -> 두꺼운 쪽 -Y (운곡교 규칙과 같음 [추론], OPEN #16)",
"src": "교량받침 A x B (550 x 550), h3 132 (ELEVATION TABLE); T = h4 23 / 24"},
"rebar_marks": {}, "rebar_marks_src": "철근 G2~G4 다음 Task",
}
expected = {
"_schema": "pier-T-expected/1", "pier_id": "P1", "tol_mm": 1.0,
"_note": "독립 기대값: 일반도 치수 문자·EL 문자·받침 표. [작도] = 치수 문자 없음(대좌 외곽, 받침 평면 위치·회전)",
"checkers": {"G1": "g1_pedestal.py"},
"negative": {"G1": [{"id": "BP02", "d": [3, 0, 0]}, {"id": "BS03", "d": [0, 0, 2]}],
"G5": [{"id": "BB04", "d": [5, 0, 0]}, {"id": "SP03", "d": [0, 0, 5]}]},
"planned_fail": [],
"G1": {"footing": {"dx": 7700, "dy": 7700, "z0": 10032, "thickness": 2600, "src": "'7.700', '2.600', 'EL. 10.032'"},
"lean": {"dx": 7900, "dy": 7900, "thickness": 100, "src": "버림 '100', 7,900"},
"column": {"d": 2200, "height": 16900, "src": "'2.200', '16.900'"},
"coping": {"bottom_flat_half": 1200, "tip_half": 6000, "soffit_rise": 1700, "width_y": 3000, "side_bottom_width": 2200,
"skew_deg": 0.0, "step_bounds": [-3723, -1216, 1291, 3798],
"step_z": [32532, 32633, 32734, 32835, 32936],
"src": "'12.000', '1.300'(좌 끝), '1.704'(우 끝), '1.700', 기둥 폭 '2.200'(평평한 하면 ±1,200: 작도), '3.000'(폭), "
"상면 단 경계 '2.277, 3@2.507, 2.202'(받침 열 기준); 단 높이 = EL.'X' - h1 - h2 (NO.1~5); 'EL. 32.532', 'EL. 32.936'"},
"seats": {"n_pedestals": 5,
"table": {str(no): [TABLE[no][0], TABLE[no][1], 50, 550, 550] for no in range(1, 11)},
"pos": {str(no): pads[no]["centre"] for no in range(1, 11)},
"src": "ELEVATION TABLE; 받침 평면 위치 [작도] (평면 치수 '1.024 / 948', S1·S2 '1000 / 997 / 1003' 일치)"}},
"G5": {"el_x": {str(no): TABLE[no][0] for no in range(1, 11)}, "S": {str(no): SOLE[no][0] for no in range(1, 11)},
"W": {str(no): 650 for no in range(1, 11)}, "L": 650,
"T": {str(no): SOLE[no][1] for no in range(1, 11)}, "h3": 132,
"bearing_size": {str(no): [550, 550] for no in range(1, 11)}, "bearing_shrink": 100,
"colours": {"bearing": [0, 0, 0], "sole_plate": [150, 150, 150]},
"src": "ELEVATION TABLE (EL.'X', h3, A, B); 솔플레이트 상세 TABLE (S, L, W, T, T1·T2; S < 0 -> 두꺼운 쪽 -Y)"},
}
if __name__ == "__main__":
if "--update" in sys.argv: # rewrite params / expected of the existing pier (values fixed after a gate run)
p = store.Pier(NAME)
params["display"] = p.load("params")["display"]
expected["rebar_palette"] = p.load("expected")["rebar_palette"]
p.save("params", params)
p.save("expected", expected)
sys.exit("updated " + str(p.dir))
if (store.DATA / NAME).exists():
sys.exit(f"pier exists: {NAME}")
c = webapp.app.test_client()
assert c.post("/pier/new", data={"name": NAME, "type": "T형", "template": "tpl:산외교울산P1형"}).status_code == 302
dwg = ROOT / "RAG" / "새재1교P1.dwg"
r = c.post(f"/pier/{NAME}/upload", data={"dwg": [(BytesIO(dwg.read_bytes()), dwg.name)]}, content_type="multipart/form-data")
assert r.status_code == 302, r.status_code
p = store.Pier(NAME)
params["display"] = p.load("params")["display"]
expected["rebar_palette"] = p.load("expected")["rebar_palette"]
p.save("params", params)
p.save("expected", expected)
meta = store.rjson(p.dir / "pier.json")
meta["template"] = "신규 판독 (새재1교 P1 판독서 v0.1.00)"
store.wjson(p.dir / "pier.json", meta)
print("created", p.dir, "texts", len(p.texts()), "profile", prof)
+17
View File
@@ -0,0 +1,17 @@
"""Run gates (default G1 then G5) of the app pier '새재1교P1' with the engine (no confirmation / approval: those are the
user's review records in the app). Results: data/새재1교P1/runs/current/G*_gate.json, G*.3dm.
usage: python run_gates.py [G1|G5 ...]"""
import json
import sys
from pathlib import Path
APP = Path(__file__).resolve().parents[2] / "Code" / "교각모델링앱"
sys.path.insert(0, str(APP))
from engine.gates import run_gate # noqa: E402
D = APP / "data" / "새재1교P1"
for g in sys.argv[1:] or ["G1", "G5"]:
rep = run_gate(g, D / "params.json", D / "expected.json", D / "runs" / "current")
print(json.dumps({k: rep[k] for k in ("gate", "verdict", "summary", "unplanned_fails", "reload", "secs")}, ensure_ascii=False))
if rep["verdict"] != "PASS":
break
@@ -0,0 +1,331 @@
{
"coping_front": {
"z_bottom": 29532.0,
"bottom_flat_half": 1200.0,
"tip_x": 6000.0,
"z_tip": 31232.0,
"end_left": {
"x": -6000.0,
"z0": 31232.0,
"z1": 32532.0
},
"end_right": {
"x": 6000.0,
"z0": 31232.0,
"z1": 32942.5
},
"top_steps": [
{
"x0": -6000.0,
"x1": -3722.5,
"z": 32532.0
},
{
"x0": -3722.5,
"x1": -1215.6,
"z": 32633.1
},
{
"x0": -1215.6,
"x1": 1291.3,
"z": 32734.1
},
{
"x0": -5626.0,
"x1": -4326.0,
"z": 32740.5
},
{
"x0": 1291.3,
"x1": 3798.2,
"z": 32835.1
},
{
"x0": -3119.1,
"x1": -1819.1,
"z": 32841.5
},
{
"x0": 3798.2,
"x1": 6000.0,
"z": 32936.1
},
{
"x0": -612.1,
"x1": 687.9,
"z": 32942.5
}
],
"verts": [
[
27756.4,
37048.5,
38348.5
],
[
32656.4,
31398.5,
35348.5
],
[
32678.6,
31398.5,
35348.5
],
[
32748.2,
31398.5,
35348.5
],
[
32876.4,
31398.5,
35348.5
],
[
33096.4,
31398.5,
35348.5
],
[
33756.4,
31398.5,
35348.5
],
[
34416.4,
31398.5,
35348.5
],
[
34636.4,
31398.5,
35348.5
],
[
34764.5,
31398.5,
35348.5
],
[
34834.1,
31398.5,
35348.5
],
[
34856.4,
31398.5,
35348.5
],
[
39756.4,
37048.5,
38752.6
]
],
"src": "D1 정면도 코핑 외곽 2F1A~2F27 (Y = 0 단면), 치수 '1.300', '1.704', '2.277', '3@2.507', '2.202'"
},
"coping_side": {
"half_width_top": 1500.0,
"z_taper_top": 31232.0,
"half_width_bottom": 1100.0,
"z_bottom": 29532.0,
"src": "D1 단면도 코핑 2DAF/2DB0 (±1,100 → ±1,500, 경사 1,746.4), 폭 3,000"
},
"column": {
"d": 2200.0,
"z0": 12632.0,
"z1": 29532.0,
"src": "D1 정면 기둥 2.200, 높이 16.900(치수), 평면 원 r 1,100 (29C8~29CF)"
},
"footing": {
"size_x": 7700.0,
"size_y": 7700.0,
"z0": 10032.0,
"z1": 12632.0,
"src": "D1 정면 2E24~2E2E (7.700 × 2.600), 기초 평면도 7.700"
},
"lean": {
"size_x": 7900.0,
"size_y": 7900.0,
"z0": 9932.0,
"z1": 10032.0,
"src": "D1 정면 2E24~2E27 (7.900 × 100)"
},
"coping_plan": {
"x": [
-6000.000000000004,
6000.0
],
"y": [
-1500.0,
1500.0
],
"step_lines_x": [
-3722.6,
-1215.6,
1291.3,
3798.2
],
"src": "D1 평면 28FA~2901 (직사각, 사각 없음)"
},
"pads_outer": {
"10": {
"centre": [
4977.2,
497.0
],
"along": 750.0,
"across": 750.0,
"rotation_deg": -6.395,
"src": "D1 평면 2989"
},
"9": {
"centre": [
2470.1,
497.0
],
"along": 750.0,
"across": 750.0,
"rotation_deg": -6.422,
"src": "D1 평면 298C"
},
"8": {
"centre": [
-37.1,
497.0
],
"along": 750.0,
"across": 750.0,
"rotation_deg": -6.449,
"src": "D1 평면 298F"
},
"7": {
"centre": [
-2544.3,
496.9
],
"along": 750.0,
"across": 750.0,
"rotation_deg": -6.476,
"src": "D1 평면 2992"
},
"6": {
"centre": [
-5051.6,
496.9
],
"along": 750.0,
"across": 750.0,
"rotation_deg": -6.503,
"src": "D1 평면 2995"
},
"5": {
"centre": [
5051.6,
-499.7
],
"along": 750.0,
"across": 750.0,
"rotation_deg": -2.135,
"src": "D1 평면 2998"
},
"4": {
"centre": [
2544.8,
-499.7
],
"along": 750.0,
"across": 750.0,
"rotation_deg": -2.144,
"src": "D1 평면 299B"
},
"3": {
"centre": [
37.9,
-499.7
],
"along": 750.0,
"across": 750.0,
"rotation_deg": -2.153,
"src": "D1 평면 299E"
},
"2": {
"centre": [
-2469.1,
-499.7
],
"along": 750.0,
"across": 750.0,
"rotation_deg": -2.162,
"src": "D1 평면 29A1"
},
"1": {
"centre": [
-4976.0,
-499.7
],
"along": 750.0,
"across": 750.0,
"rotation_deg": -2.171,
"src": "D1 평면 29A4"
}
},
"pedestals": [
{
"x": [
-5626.0,
-4326.0
],
"y": [
-1199.7,
1197.0
],
"src": "D1 평면 대좌 28D6~28F9"
},
{
"x": [
-3119.1,
-1819.1
],
"y": [
-1199.7,
1197.0
],
"src": "D1 평면 대좌 28D6~28F9"
},
{
"x": [
-612.1,
687.9
],
"y": [
-1199.7,
1197.0
],
"src": "D1 평면 대좌 28D6~28F9"
},
{
"x": [
1894.8,
3194.8
],
"y": [
-1199.7,
1197.0
],
"src": "D1 평면 대좌 28D6~28F9"
},
{
"x": [
4401.6,
5701.6
],
"y": [
-1199.7,
1197.0
],
"src": "D1 평면 대좌 28D6~28F9"
}
]
}
@@ -0,0 +1,278 @@
{
"hoops_drawn": {
"count": 42,
"levels": [
11432.0,
11732.0,
12032.0,
12332.0,
12632.0,
12782.0,
12932.0,
13082.0,
13232.0,
13382.0,
13532.0,
13682.0,
13832.0,
13982.0,
14132.0,
14282.0,
14432.0,
14582.0,
14732.0,
14882.0,
15032.0,
15182.0,
15332.0,
15632.0,
15932.0,
16232.0,
16532.0,
16932.0,
17232.0,
17532.0,
17832.0,
18132.0,
18432.0,
18732.0,
19032.0,
19332.0,
19632.0,
19932.0,
20232.0,
20532.0,
20832.0,
21132.0
]
},
"sections": [
{
"centre": [
268681,
23662
],
"rings": {
"975.0": 49,
"930.0": 49
},
"angle_pitch": 7.347,
"n_outer": 49
},
{
"centre": [
260729,
23598
],
"rings": {
"975.0": 49,
"930.0": 49
},
"angle_pitch": 7.347,
"n_outer": 49
},
{
"centre": [
290798,
33491
],
"rings": {
"975.0": 49,
"930.0": 49
},
"angle_pitch": 7.347,
"n_outer": 49
},
{
"centre": [
283884,
33520
],
"rings": {
"975.0": 49,
"930.0": 49
},
"angle_pitch": 7.347,
"n_outer": 49
},
{
"centre": [
276837,
33398
],
"rings": {
"975.0": 49,
"930.0": 49
},
"angle_pitch": 7.347,
"n_outer": 49
}
],
"section_ties": {
"x_line": [
-996.7000000000116,
997.7000000000116
],
"y_offset": 25.0,
"length": 1994.4,
"hoop_arc_r": 997.5
},
"hoops_chain": [
11432.0,
11732.0,
12032.0,
12332.0,
12632.0,
12782.0,
12932.0,
13082.0,
13232.0,
13382.0,
13532.0,
13682.0,
13832.0,
13982.0,
14132.0,
14282.0,
14432.0,
14582.0,
14732.0,
14882.0,
15032.0,
15182.0,
15332.0,
15632.0,
15932.0,
16232.0,
16532.0,
16832.0,
17132.0,
17432.0,
17732.0,
18032.0,
18332.0,
18632.0,
18932.0,
19232.0,
19532.0,
19832.0,
20132.0,
20432.0,
20732.0,
21032.0,
21332.0,
21632.0,
21932.0,
22232.0,
22532.0,
22832.0,
23132.0,
23432.0,
23732.0,
24032.0,
24332.0,
24632.0,
24932.0,
25232.0,
25532.0,
25832.0,
26132.0,
26432.0,
26732.0,
27032.0,
27332.0,
27632.0,
27932.0,
28232.0,
28532.0,
28832.0,
29132.0,
29432.0,
29732.0,
30032.0
],
"ties_chain": [
11082.0,
11682.0,
11982.0,
12282.0,
12582.0,
12882.0,
13182.0,
13482.0,
13782.0,
14382.0,
14982.0,
15582.0,
16182.0,
16782.0,
17382.0,
17982.0,
18582.0,
19182.0,
19782.0,
20382.0,
20982.0,
21582.0,
22182.0,
22782.0,
23082.0,
23382.0,
23682.0,
23982.0,
24282.0,
24582.0,
24882.0,
25182.0,
25482.0,
25782.0,
26082.0,
26382.0,
26682.0,
26982.0,
27582.0,
28182.0
],
"hoop_zones": [
[
"P3",
5
],
[
"P4",
18
],
[
"P3",
36
],
[
"P4",
9
],
[
"P3",
4
]
],
"check": {
"n_hoops": 72,
"n_tie_levels": 40,
"hoops_end_to_coping_top": 32532.0,
"drawn_subset_of_chain": true,
"drawn_beyond_break_not_on_chain": [
16932.0,
17232.0,
17532.0,
17832.0,
18132.0,
18432.0,
18732.0,
19032.0,
19332.0,
19632.0,
19932.0,
20232.0
]
}
}
@@ -0,0 +1 @@
{"bars": [{"mark": "B2", "occ": "y-3750.0", "pts": [[-3750.0, -3750.0, 11932.0], [-3750.0, -3750.0, 10132.0], [-3750.0, 3750.0, 10132.0], [-3750.0, 3750.0, 11932.0]], "r": 56.25, "design_length": 12010, "src": "정면 하면 점 EL 10.132, 측면 다리 1,800; B2/B4 교번, 겹이음 j 미모델 (F3 [추론])"}, {"mark": "B4", "occ": "y-3675.0", "pts": [[-3675.0, -3750.0, 11932.0], [-3675.0, -3750.0, 10132.0], [-3675.0, 3750.0, 10132.0], [-3675.0, 3750.0, 11932.0]], "r": 56.25, "design_length": 12010, "src": "정면 하면 점 EL 10.132, 측면 다리 1,800; B2/B4 교번, 겹이음 j 미모델 (F3 [추론])"}, {"mark": "B2", "occ": "y-3600.0", "pts": [[-3600.0, -3750.0, 11932.0], [-3600.0, -3750.0, 10132.0], [-3600.0, 3750.0, 10132.0], [-3600.0, 3750.0, 11932.0]], "r": 56.25, "design_length": 12010, "src": "정면 하면 점 EL 10.132, 측면 다리 1,800; B2/B4 교번, 겹이음 j 미모델 (F3 [추론])"}, {"mark": "B4", "occ": "y-3475.0", "pts": [[-3475.0, -3750.0, 11932.0], [-3475.0, -3750.0, 10132.0], [-3475.0, 3750.0, 10132.0], [-3475.0, 3750.0, 11932.0]], "r": 56.25, "design_length": 12010, "src": "정면 하면 점 EL 10.132, 측면 다리 1,800; B2/B4 교번, 겹이음 j 미모델 (F3 [추론])"}, {"mark": "B2", "occ": "y-3350.0", "pts": [[-3350.0, -3750.0, 11932.0], [-3350.0, -3750.0, 10132.0], [-3350.0, 3750.0, 10132.0], [-3350.0, 3750.0, 11932.0]], "r": 56.25, "design_length": 12010, "src": "정면 하면 점 EL 10.132, 측면 다리 1,800; B2/B4 교번, 겹이음 j 미모델 (F3 [추론])"}, {"mark": "B4", "occ": "y-3225.0", "pts": [[-3225.0, -3750.0, 11932.0], [-3225.0, -3750.0, 10132.0], [-3225.0, 3750.0, 10132.0], [-3225.0, 3750.0, 11932.0]], "r": 56.25, "design_length": 12010, "src": "정면 하면 점 EL 10.132, 측면 다리 1,800; B2/B4 교번, 겹이음 j 미모델 (F3 [추론])"}, {"mark": "B2", "occ": "y-3100.0", "pts": [[-3100.0, -3750.0, 11932.0], [-3100.0, -3750.0, 10132.0], [-3100.0, 3750.0, 10132.0], [-3100.0, 3750.0, 11932.0]], "r": 56.25, "design_length": 12010, "src": "정면 하면 점 EL 10.132, 측면 다리 1,800; B2/B4 교번, 겹이음 j 미모델 (F3 [추론])"}, {"mark": "B4", "occ": "y-2975.0", "pts": [[-2975.0, -3750.0, 11932.0], [-2975.0, -3750.0, 10132.0], [-2975.0, 3750.0, 10132.0], [-2975.0, 3750.0, 11932.0]], "r": 56.25, "design_length": 12010, "src": "정면 하면 점 EL 10.132, 측면 다리 1,800; B2/B4 교번, 겹이음 j 미모델 (F3 [추론])"}, {"mark": "B2", "occ": "y-2850.0", "pts": [[-2850.0, -3750.0, 11932.0], [-2850.0, -3750.0, 10132.0], [-2850.0, 3750.0, 10132.0], [-2850.0, 3750.0, 11932.0]], "r": 56.25, "design_length": 12010, "src": "정면 하면 점 EL 10.132, 측면 다리 1,800; B2/B4 교번, 겹이음 j 미모델 (F3 [추론])"}, {"mark": "B4", "occ": "y-2725.0", "pts": [[-2725.0, -3750.0, 11932.0], [-2725.0, -3750.0, 10132.0], [-2725.0, 3750.0, 10132.0], [-2725.0, 3750.0, 11932.0]], "r": 56.25, "design_length": 12010, "src": "정면 하면 점 EL 10.132, 측면 다리 1,800; B2/B4 교번, 겹이음 j 미모델 (F3 [추론])"}, {"mark": "B2", "occ": "y-2600.0", "pts": [[-2600.0, -3750.0, 11932.0], [-2600.0, -3750.0, 10132.0], [-2600.0, 3750.0, 10132.0], [-2600.0, 3750.0, 11932.0]], "r": 56.25, "design_length": 12010, "src": "정면 하면 점 EL 10.132, 측면 다리 1,800; B2/B4 교번, 겹이음 j 미모델 (F3 [추론])"}, {"mark": "B4", "occ": "y-2475.0", "pts": [[-2475.0, -3750.0, 11932.0], [-2475.0, -3750.0, 10132.0], [-2475.0, 3750.0, 10132.0], [-2475.0, 3750.0, 11932.0]], "r": 56.25, "design_length": 12010, "src": "정면 하면 점 EL 10.132, 측면 다리 1,800; B2/B4 교번, 겹이음 j 미모델 (F3 [추론])"}, {"mark": "B2", "occ": "y-2350.0", "pts": [[-2350.0, -3750.0, 11932.0], [-2350.0, -3750.0, 10132.0], [-2350.0, 3750.0, 10132.0], [-2350.0, 3750.0, 11932.0]], "r": 56.25, "design_length": 12010, "src": "정면 하면 점 EL 10.132, 측면 다리 1,800; B2/B4 교번, 겹이음 j 미모델 (F3 [추론])"}, {"mark": "B4", "occ": "y-2225.0", "pts": [[-2225.0, -3750.0, 11932.0], [-2225.0, -3750.0, 10132.0], [-2225.0, 3750.0, 10132.0], [-2225.0, 3750.0, 11932.0]], "r": 56.25, "design_length": 12010, "src": "정면 하면 점 EL 10.132, 측면 다리 1,800; B2/B4 교번, 겹이음 j 미모델 (F3 [추론])"}, {"mark": "B2", "occ": "y-2100.0", "pts": [[-2100.0, -3750.0, 11932.0], [-2100.0, -3750.0, 10132.0], [-2100.0, 3750.0, 10132.0], [-2100.0, 3750.0, 11932.0]], "r": 56.25, "design_length": 12010, "src": "정면 하면 점 EL 10.132, 측면 다리 1,800; B2/B4 교번, 겹이음 j 미모델 (F3 [추론])"}, {"mark": "B4", "occ": "y-1975.0", "pts": [[-1975.0, -3750.0, 11932.0], [-1975.0, -3750.0, 10132.0], [-1975.0, 3750.0, 10132.0], [-1975.0, 3750.0, 11932.0]], "r": 56.25, "design_length": 12010, "src": "정면 하면 점 EL 10.132, 측면 다리 1,800; B2/B4 교번, 겹이음 j 미모델 (F3 [추론])"}, {"mark": "B2", "occ": "y-1850.0", "pts": [[-1850.0, -3750.0, 11932.0], [-1850.0, -3750.0, 10132.0], [-1850.0, 3750.0, 10132.0Line truncated
@@ -0,0 +1,343 @@
{
"y_bars_bottom": {
"z": 10132.0,
"x": [
-3750.0,
-3675.0,
-3600.0,
-3475.0,
-3350.0,
-3225.0,
-3100.0,
-2975.0,
-2850.0,
-2725.0,
-2600.0,
-2475.0,
-2350.0,
-2225.0,
-2100.0,
-1975.0,
-1850.0,
-1725.0,
-1600.0,
-1475.0,
-1350.0,
-1225.0,
-1100.0,
-975.0,
-850.0,
-725.0,
-600.0,
-475.0,
-350.0,
-225.0,
-100.0,
25.0,
150.0,
275.0,
400.0,
525.0,
650.0,
775.0,
900.0,
1025.0,
1150.0,
1275.0,
1400.0,
1525.0,
1650.0,
1775.0,
1900.0,
2025.0,
2150.0,
2275.0,
2400.0,
2525.0,
2650.0,
2775.0,
2900.0,
3025.0,
3150.0,
3275.0,
3400.0,
3525.0,
3650.0
]
},
"y_bars_top": {
"z": 12532.0,
"x": [
-3750.0,
-3675.0,
-3600.0,
-3475.0,
-3350.0,
-3225.0,
-3100.0,
-2975.0,
-2850.0,
-2725.0,
-2600.0,
-2475.0,
-2350.0,
-2225.0,
-2100.0,
-1975.0,
-1850.0,
-1725.0,
-1600.0,
-1475.0,
-1350.0,
-1225.0,
-1100.0,
-975.0,
-850.0,
-725.0,
-600.0,
-475.0,
-350.0,
-225.0,
-100.0,
25.0,
150.0,
275.0,
400.0,
525.0,
650.0,
775.0,
900.0,
1025.0,
1150.0,
1275.0,
1400.0,
1525.0,
1650.0,
1775.0,
1900.0,
2025.0,
2150.0,
2275.0,
2400.0,
2525.0,
2650.0,
2775.0,
2900.0,
3025.0,
3150.0,
3275.0,
3400.0,
3525.0,
3650.0
]
},
"x_bars_bottom": {
"z": 10154.5,
"y": [
-3750.0,
-3600.0,
-3450.0,
-3300.0,
-3150.0,
-3000.0,
-2850.0,
-2700.0,
-2550.0,
-2400.0,
-2250.0,
-2100.0,
-1950.0,
-1800.0,
-1650.0,
-1500.0,
-1350.0,
-1200.0,
-1050.0,
-900.0,
-750.0,
-600.0,
-450.0,
-300.0,
-150.0,
-0.0,
150.0,
300.0,
450.0,
600.0,
750.0,
900.0,
1050.0,
1200.0,
1350.0,
1500.0,
1650.0,
1800.0,
1950.0,
2100.0,
2250.0,
2400.0,
2550.0,
2700.0,
2850.0,
3000.0,
3150.0,
3300.0,
3450.0,
3600.0,
3750.0
]
},
"x_bars_top": {
"z": 12509.5,
"y": [
-3750.0,
-3600.0,
-3450.0,
-3300.0,
-3150.0,
-3000.0,
-2850.0,
-2700.0,
-2550.0,
-2400.0,
-2250.0,
-2100.0,
-1950.0,
-1800.0,
-1650.0,
-1500.0,
-1350.0,
-1200.0,
-1050.0,
-900.0,
-750.0,
-600.0,
-450.0,
-300.0,
-150.0,
-0.0,
150.0,
300.0,
450.0,
600.0,
750.0,
900.0,
1050.0,
1200.0,
1350.0,
1500.0,
1650.0,
1800.0,
1950.0,
2100.0,
2250.0,
2400.0,
2550.0,
2700.0,
2850.0,
3000.0,
3150.0,
3300.0,
3450.0,
3600.0,
3750.0
]
},
"mid_y_bars": {
"10732": [
-3600.0,
-2600.0,
-1600.0,
-600.0,
400.0,
1400.0,
2400.0,
3400.0
],
"11332": [
-3100.0,
-2100.0,
-1100.0,
-100.0,
900.0,
1900.0,
2900.0
],
"11632": [
-3600.0,
-2600.0,
-1600.0,
-600.0,
400.0,
1400.0,
2400.0,
3400.0
]
},
"mid_x_bars": {
"10732": [
-3450.0,
-1050.0,
1350.0,
3750.0
],
"11332": [
-2250.0,
150.0,
2550.0
],
"11632": [
-3450.0,
-1050.0,
1350.0,
3750.0
]
},
"b10_levels": [
10432.0,
10732.0,
11332.0,
11632.0
],
"b10_corner": 3772.5,
"b9": {
"cols_even": [
-3600.0,
-2600.0,
-1600.0,
-600.0,
400.0,
1400.0,
2400.0,
3400.0
],
"cols_odd": [
-3100.0,
-2100.0,
-1100.0,
-100.0,
900.0,
1900.0,
2900.0
],
"rows": [
-2850.0,
-1650.0,
-450.0,
750.0,
1950.0,
3150.0
],
"a": 1244.0,
"b": 2444.0,
"c": 100.0,
"zt": 12554.0,
"zb": 10110.0
},
"counts": {
"y_bars_bottom": 61,
"y_bars_top": 61,
"x_bars_bottom": 51,
"x_bars_top": 51
}
}
@@ -0,0 +1 @@
{"bars": [{"mark": "C1", "occ": "y-1375", "pts": [[-5875, -1375.0, 31320.0], [-5875, -1375.0, 32407.0], [5875, -1375.0, 32407.0], [5875, -1375.0, 31320.0]], "r": 65.25, "design_length": 13924.0, "src": "정면 선 EL 32.407, x ±5,875, 다리 1087; 단면 사슬 23줄 @125, 교번 [추론 F3형], 겹이음 j 미모델"}, {"mark": "C4", "occ": "y-1250", "pts": [[-5875, -1250.0, 31320.0], [-5875, -1250.0, 32407.0], [5875, -1250.0, 32407.0], [5875, -1250.0, 31320.0]], "r": 65.25, "design_length": 13924.0, "src": "정면 선 EL 32.407, x ±5,875, 다리 1087; 단면 사슬 23줄 @125, 교번 [추론 F3형], 겹이음 j 미모델"}, {"mark": "C1", "occ": "y-1125", "pts": [[-5875, -1125.0, 31320.0], [-5875, -1125.0, 32407.0], [5875, -1125.0, 32407.0], [5875, -1125.0, 31320.0]], "r": 65.25, "design_length": 13924.0, "src": "정면 선 EL 32.407, x ±5,875, 다리 1087; 단면 사슬 23줄 @125, 교번 [추론 F3형], 겹이음 j 미모델"}, {"mark": "C4", "occ": "y-1000", "pts": [[-5875, -1000.0, 31320.0], [-5875, -1000.0, 32407.0], [5875, -1000.0, 32407.0], [5875, -1000.0, 31320.0]], "r": 65.25, "design_length": 13924.0, "src": "정면 선 EL 32.407, x ±5,875, 다리 1087; 단면 사슬 23줄 @125, 교번 [추론 F3형], 겹이음 j 미모델"}, {"mark": "C1", "occ": "y-875", "pts": [[-5875, -875.0, 31320.0], [-5875, -875.0, 32407.0], [5875, -875.0, 32407.0], [5875, -875.0, 31320.0]], "r": 65.25, "design_length": 13924.0, "src": "정면 선 EL 32.407, x ±5,875, 다리 1087; 단면 사슬 23줄 @125, 교번 [추론 F3형], 겹이음 j 미모델"}, {"mark": "C4", "occ": "y-750", "pts": [[-5875, -750.0, 31320.0], [-5875, -750.0, 32407.0], [5875, -750.0, 32407.0], [5875, -750.0, 31320.0]], "r": 65.25, "design_length": 13924.0, "src": "정면 선 EL 32.407, x ±5,875, 다리 1087; 단면 사슬 23줄 @125, 교번 [추론 F3형], 겹이음 j 미모델"}, {"mark": "C1", "occ": "y-625", "pts": [[-5875, -625.0, 31320.0], [-5875, -625.0, 32407.0], [5875, -625.0, 32407.0], [5875, -625.0, 31320.0]], "r": 65.25, "design_length": 13924.0, "src": "정면 선 EL 32.407, x ±5,875, 다리 1087; 단면 사슬 23줄 @125, 교번 [추론 F3형], 겹이음 j 미모델"}, {"mark": "C4", "occ": "y-500", "pts": [[-5875, -500.0, 31320.0], [-5875, -500.0, 32407.0], [5875, -500.0, 32407.0], [5875, -500.0, 31320.0]], "r": 65.25, "design_length": 13924.0, "src": "정면 선 EL 32.407, x ±5,875, 다리 1087; 단면 사슬 23줄 @125, 교번 [추론 F3형], 겹이음 j 미모델"}, {"mark": "C1", "occ": "y-375", "pts": [[-5875, -375.0, 31320.0], [-5875, -375.0, 32407.0], [5875, -375.0, 32407.0], [5875, -375.0, 31320.0]], "r": 65.25, "design_length": 13924.0, "src": "정면 선 EL 32.407, x ±5,875, 다리 1087; 단면 사슬 23줄 @125, 교번 [추론 F3형], 겹이음 j 미모델"}, {"mark": "C4", "occ": "y-250", "pts": [[-5875, -250.0, 31320.0], [-5875, -250.0, 32407.0], [5875, -250.0, 32407.0], [5875, -250.0, 31320.0]], "r": 65.25, "design_length": 13924.0, "src": "정면 선 EL 32.407, x ±5,875, 다리 1087; 단면 사슬 23줄 @125, 교번 [추론 F3형], 겹이음 j 미모델"}, {"mark": "C1", "occ": "y-125", "pts": [[-5875, -125.0, 31320.0], [-5875, -125.0, 32407.0], [5875, -125.0, 32407.0], [5875, -125.0, 31320.0]], "r": 65.25, "design_length": 13924.0, "src": "정면 선 EL 32.407, x ±5,875, 다리 1087; 단면 사슬 23줄 @125, 교번 [추론 F3형], 겹이음 j 미모델"}, {"mark": "C4", "occ": "y+0", "pts": [[-5875, 0.0, 31320.0], [-5875, 0.0, 32407.0], [5875, 0.0, 32407.0], [5875, 0.0, 31320.0]], "r": 65.25, "design_length": 13924.0, "src": "정면 선 EL 32.407, x ±5,875, 다리 1087; 단면 사슬 23줄 @125, 교번 [추론 F3형], 겹이음 j 미모델"}, {"mark": "C1", "occ": "y+125", "pts": [[-5875, 125.0, 31320.0], [-5875, 125.0, 32407.0], [5875, 125.0, 32407.0], [5875, 125.0, 31320.0]], "r": 65.25, "design_length": 13924.0, "src": "정면 선 EL 32.407, x ±5,875, 다리 1087; 단면 사슬 23줄 @125, 교번 [추론 F3형], 겹이음 j 미모델"}, {"mark": "C4", "occ": "y+250", "pts": [[-5875, 250.0, 31320.0], [-5875, 250.0, 32407.0], [5875, 250.0, 32407.0], [5875, 250.0, 31320.0]], "r": 65.25, "design_length": 13924.0, "src": "정면 선 EL 32.407, x ±5,875, 다리 1087; 단면 사슬 23줄 @125, 교번 [추론 F3형], 겹이음 j 미모델"}, {"mark": "C1", "occ": "y+375", "pts": [[-5875, 375.0, 31320.0], [-5875, 375.0, 32407.0], [5875, 375.0, 32407.0], [5875, 375.0, 31320.0]], "r": 65.25, "design_length": 13924.0, "src": "정면 선 EL 32.407, x ±5,875, 다리 1087; 단면 사슬 23줄 @125, 교번 [추론 F3형], 겹이음 j 미모델"}, {"mark": "C4", "occ": "y+500", "pts": [[-5875, 500.0, 31320.0], [-5875, 500.0, 32407.0], [5875, 500.0, 32407.0], [5875, 500.0, 31320.0]], "r": 65.25, "design_length": 13924.0, "src": "정면 선 EL 32.407, x ±5,875, 다리 1087; 단면 사슬 23줄 @125, 교번 [추론 F3형], 겹이음 j 미모델"}, {"mark": "C1", "occ": "y+625", "pts": [[-5875, 625.0, 31320.0], [-5875,Line truncated
Binary file not shown.

After

Width:  |  Height:  |  Size: 529 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 457 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 430 KiB