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

@@ -0,0 +1,916 @@
{
"enum_count": 3236,
"units": "Millimeters",
"total": 3236,
"layers": [
{
"layer": "P1::검토표시",
"type": "Brep",
"count": 14,
"sample": {
"name": "검토_M-04",
"userstrings": {}
}
},
{
"layer": "P1::검토표시",
"type": "Curve",
"count": 14,
"sample": {
"name": "검토_M-04",
"userstrings": {},
"curve": {
"len": 16911.08559495812,
"type": "LineCurve",
"closed": false
}
}
},
{
"layer": "P1::검토표시",
"type": "TextDot",
"count": 14,
"sample": {
"name": "검토_E-01",
"userstrings": {}
}
},
{
"layer": "P1::교량받침",
"type": "Brep",
"count": 10,
"sample": {
"name": "P1-BB10",
"userstrings": {
"id": "P1-BB10",
"role": "bridge bearing",
"no": "10",
"size": "700x540x181",
"el_x": "43887",
"src": "D2 ELEVATION TABLE h3, (L-100)x(W-100) per user 2026-10-08"
}
}
},
{
"layer": "P1::기둥",
"type": "Brep",
"count": 1,
"sample": {
"name": "P1-CL",
"userstrings": {
"id": "P1-CL",
"role": "column",
"fck": "40MPa",
"source_views": "D1 정면도, D1 단면도, D1 단면 C-C/D-D/E-E, D2 기초평면도"
}
}
},
{
"layer": "P1::기초",
"type": "Brep",
"count": 1,
"sample": {
"name": "P1-FT",
"userstrings": {
"id": "P1-FT",
"role": "footing",
"fck": "27MPa",
"source_views": "D1 정면도, D1 단면도, D2 기초평면도"
}
}
},
{
"layer": "P1::말뚝",
"type": "Brep",
"count": 30,
"sample": {
"name": "P1-PL30",
"userstrings": {
"id": "P1-PL30",
"role": "composite pile D600 L24.4m",
"fck": "-",
"source_views": "D1 정면도, D1 단면도"
}
}
},
{
"layer": "P1::받침대좌",
"type": "Brep",
"count": 10,
"sample": {
"name": "P1-BS10",
"userstrings": {
"id": "P1-BS10",
"role": "bearing pedestal h1 NO.10 girder 5 rear",
"fck": "40MPa",
"source_views": "D1 평면도, D1 단면도, D2 ELEVATION TABLE"
}
}
},
{
"layer": "P1::받침패드",
"type": "Brep",
"count": 10,
"sample": {
"name": "P1-BP10",
"userstrings": {
"id": "P1-BP10",
"role": "bearing pad h2 NO.10 2800 kN 양방향",
"fck": "-",
"source_views": "D1 평면도, D1 단면도, D2 교량받침 상세·ELEVATION TABLE"
}
}
},
{
"layer": "P1::버림콘크리트",
"type": "Brep",
"count": 1,
"sample": {
"name": "P1-LC",
"userstrings": {
"id": "P1-LC",
"role": "lean concrete",
"fck": "15MPa",
"source_views": "D1 정면도, D1 단면도"
}
}
},
{
"layer": "P1::솔플레이트",
"type": "Brep",
"count": 10,
"sample": {
"name": "P1-SP10",
"userstrings": {
"id": "P1-SP10",
"role": "sole plate",
"no": "10",
"S": "-1.901",
"L": "800",
"W": "640",
"T": "30",
"end_thick": "37.60/22.40",
"src": "D2 솔플레이트 상세 TABLE; slope along pad axis, thick end -Y [HITL]"
}
}
},
{
"layer": "P1::철근",
"type": "Annotation",
"count": 4,
"sample": {
"name": null,
"userstrings": {}
}
},
{
"layer": "P1::철근::기둥::P1",
"type": "Brep",
"count": 46,
"sample": {
"name": "P1-R-P1-46",
"userstrings": {
"id": "P1-R-P1-46",
"mark": "P1",
"dia": "S32",
"shape": "XIV",
"occurrence": "46",
"host": "P1-CL",
"anchor_hosts": "P1-FT,P1-CP",
"design_length": "17247.071",
"coupler_length": "0.000",
"src": "angle 352.1739 deg; D1 단면 C-C / 정면도; D3 P1"
}
}
},
{
"layer": "P1::철근::기둥::P2",
"type": "Brep",
"count": 46,
"sample": {
"name": "P1-R-P2-46",
"userstrings": {
"id": "P1-R-P2-46",
"mark": "P2",
"dia": "S32",
"shape": "XVI",
"occurrence": "46",
"host": "P1-CL",
"anchor_hosts": "P1-FT,P1-CP",
"design_length": "16553.000",
"coupler_length": "0.000",
"src": "angle 352.1739 deg; D1 단면 C-C / 정면도; D3 P2"
}
}
},
{
"layer": "P1::철근::기둥::P3",
"type": "Brep",
"count": 72,
"sample": {
"name": "P1-R-P3-L67b",
"userstrings": {
"id": "P1-R-P3-L67b",
"mark": "P3",
"dia": "H19",
"shape": "VI",
"occurrence": "L67b",
"host": "P1-CL",
"anchor_hosts": "P1-CP",
"design_length": "3218.000",
"coupler_length": "0.000",
"src": "EL 41.788; joins at 0/180 deg"
}
}
},
{
"layer": "P1::철근::기둥::P4",
"type": "Brep",
"count": 18,
"sample": {
"name": "P1-R-P4-L09b",
"userstrings": {
"id": "P1-R-P4-L09b",
"mark": "P4",
"dia": "H19",
"shape": "V",
"occurrence": "L09b",
"host": "P1-CL",
"design_length": "2753.000",
"coupler_length": "65.000",
"src": "EL 28.348; coupler gap 65 at 90/270 deg"
}
}
},
{
"layer": "P1::철근::기둥::P5",
"type": "Brep",
"count": 22,
"sample": {
"name": "P1-R-P5-L31",
"userstrings": {
"id": "P1-R-P5-L31",
"mark": "P5",
"dia": "H19",
"shape": "IX",
"occurrence": "L31",
"host": "P1-CL",
"design_length": "5571.000",
"coupler_length": "65.000",
"src": "EL 30.988; coupler gap 65 at 90 deg"
}
}
},
{
"layer": "P1::철근::기둥::P6",
"type": "Brep",
"count": 36,
"sample": {
"name": "P1-R-P6-L9-135",
"userstrings": {
"id": "P1-R-P6-L9-135",
"mark": "P6",
"dia": "H16",
"shape": "III",
"occurrence": "L9-135",
"host": "P1-CL",
"anchor_hosts": "P1-CP",
"design_length": "2136.000",
"coupler_length": "0.000",
"src": "EL 41.788 (+17.5 on hoop); angle 135 deg"
}
}
},
{
"layer": "P1::철근::기초::B1",
"type": "Brep",
"count": 38,
"sample": {
"name": "P1-R-B1-y+4575",
"userstrings": {
"id": "P1-R-B1-y+4575",
"mark": "B1",
"dia": "S25",
"shape": "III",
"occurrence": "y+4575",
"host": "P1-FT",
"design_length": "8000.000",
"coupler_length": "0.000",
"src": "D1 정면도 점 z2073.0"
}
}
},
{
"layer": "P1::철근::기초::B10",
"type": "Brep",
"count": 9,
"sample": {
"name": "P1-R-B10-z1950",
"userstrings": {
"id": "P1-R-B10-z1950",
"mark": "B10",
"dia": "S19",
"shape": "XIII",
"occurrence": "z1950",
"host": "P1-FT",
"design_length": "33684.000",
"coupler_length": "0.000",
"src": "D1 정면도 '150','9@200'; D3 B10 9.198x7.644 (closed, start/end at -X mid side)"
}
}
},
{
"layer": "P1::철근::기초::B11",
"type": "Brep",
"count": 28,
"sample": {
"name": "P1-R-B11-z1750x+3250",
"userstrings": {
"id": "P1-R-B11-z1750x+3250",
"mark": "B11",
"dia": "S16",
"shape": "XII",
"occurrence": "z1750x+3250",
"host": "P1-FT",
"design_length": "9350.000",
"coupler_length": "0.000",
"src": "D1 단면도 중앙 점 z1750.0"
}
}
},
{
"layer": "P1::철근::기초::B12",
"type": "Brep",
"count": 28,
"sample": {
"name": "P1-R-B12-z1750y+3375",
"userstrings": {
"id": "P1-R-B12-z1750y+3375",
"mark": "B12",
"dia": "S16",
"shape": "III",
"occurrence": "z1750y+3375",
"host": "P1-FT",
"design_length": "7800.000",
"coupler_length": "0.000",
"src": "D1 정면도 중앙 점 z1750.0"
}
}
},
{
"layer": "P1::철근::기초::B2",
"type": "Brep",
"count": 38,
"sample": {
"name": "P1-R-B2-x+4575",
"userstrings": {
"id": "P1-R-B2-x+4575",
"mark": "B2",
"dia": "S25",
"shape": "XII",
"occurrence": "x+4575",
"host": "P1-FT",
"design_length": "11500.000",
"coupler_length": "0.000",
"src": "D1 정면도 하면 점 z122 / D1·D2 '70@125=8.750'"
}
}
},
{
"layer": "P1::철근::기초::B3",
"type": "Brep",
"count": 38,
"sample": {
"name": "P1-R-B3-y+4575",
"userstrings": {
"id": "P1-R-B3-y+4575",
"mark": "B3",
"dia": "S19",
"shape": "III",
"occurrence": "y+4575",
"host": "P1-FT",
"design_length": "8000.000",
"coupler_length": "0.000",
"src": "D1 정면도 점 z227.5"
}
}
},
{
"layer": "P1::철근::기초::B4",
"type": "Brep",
"count": 35,
"sample": {
"name": "P1-R-B4-x+4250",
"userstrings": {
"id": "P1-R-B4-x+4250",
"mark": "B4",
"dia": "S25",
"shape": "I",
"occurrence": "x+4250",
"host": "P1-FT",
"design_length": "7600.000",
"coupler_length": "0.000",
"src": "D1 정면도 하면 점 z122 / D1·D2 '70@125=8.750'"
}
}
},
{
"layer": "P1::철근::기초::B5",
"type": "Brep",
"count": 32,
"sample": {
"name": "P1-R-B5-x+3800",
"userstrings": {
"id": "P1-R-B5-x+3800",
"mark": "B5",
"dia": "S29",
"shape": "XII",
"occurrence": "x+3800",
"host": "P1-FT",
"design_length": "9550.000",
"coupler_length": "0.000",
"src": "D1 단면도 점 z2127.0"
}
}
},
{
"layer": "P1::철근::기초::B6",
"type": "Brep",
"count": 32,
"sample": {
"name": "P1-R-B6-y+3800",
"userstrings": {
"id": "P1-R-B6-y+3800",
"mark": "B6",
"dia": "S29",
"shape": "XII",
"occurrence": "y+3800",
"host": "P1-FT",
"design_length": "13050.000",
"coupler_length": "0.000",
"src": "D1 단면도 하면 점 z178 / D1 '58@125=7.250'"
}
}
},
{
"layer": "P1::철근::기초::B7",
"type": "Brep",
"count": 32,
"sample": {
"name": "P1-R-B7-x+3800",
"userstrings": {
"id": "P1-R-B7-x+3800",
"mark": "B7",
"dia": "S19",
"shape": "XII",
"occurrence": "x+3800",
"host": "P1-FT",
"design_length": "9550.000",
"coupler_length": "0.000",
"src": "D1 단면도 점 z277.0"
}
}
},
{
"layer": "P1::철근::기초::B8",
"type": "Brep",
"count": 29,
"sample": {
"name": "P1-R-B8-y+3500",
"userstrings": {
"id": "P1-R-B8-y+3500",
"mark": "B8",
"dia": "S29",
"shape": "XVI",
"occurrence": "y+3500",
"host": "P1-FT",
"design_length": "9150.000",
"coupler_length": "0.000",
"src": "D1 단면도 하면 점 z178 / D1 '58@125=7.250'"
}
}
},
{
"layer": "P1::철근::기초::B9",
"type": "Brep",
"count": 493,
"sample": {
"name": "P1-R-B9-x+4125y+3250",
"userstrings": {
"id": "P1-R-B9-x+4125y+3250",
"mark": "B9",
"dia": "H16",
"shape": "XI",
"occurrence": "x+4125y+3250",
"host": "P1-FT",
"design_length": "2155.000",
"coupler_length": "0.000",
"src": "D1 EREC grid @250 checker (i+j even) [추론]; count 493 [역산]"
}
}
},
{
"layer": "P1::철근::중심선",
"type": "Curve",
"count": 1558,
"sample": {
"name": "P1-RC-S2-g5a+1200",
"userstrings": {
"id": "P1-RC-S2-g5a+1200",
"mark": "S2",
"dia": "H19",
"shape": "III",
"occurrence": "g5a+1200",
"host": "P1-CP",
"design_length": "2500.000",
"coupler_length": "0.000",
"src": "girder 5 pedestal; lower layer"
},
"curve": {
"len": 2463.3030859409637,
"type": "PolyCurve",
"closed": false,
"segs": [
"PolylineCurve",
"ArcCurve",
"PolylineCurve",
"ArcCurve",
"PolylineCurve"
]
}
}
},
{
"layer": "P1::철근::코핑::C1",
"type": "Brep",
"count": 12,
"sample": {
"name": "P1-R-C1-t1y+1312",
"userstrings": {
"id": "P1-R-C1-t1y+1312",
"mark": "C1",
"dia": "H29",
"shape": "VIII",
"occurrence": "t1y+1312",
"host": "P1-CP",
"design_length": "14489.000",
"coupler_length": "0.000",
"src": "tier 1 EL 43.311; end inset 100.8; legs parallel to end faces",
"a_model": "11855.000"
}
}
},
{
"layer": "P1::철근::코핑::C10",
"type": "Brep",
"count": 21,
"sample": {
"name": "P1-R-C10-x-900k3",
"userstrings": {
"id": "P1-R-C10-x-900k3",
"mark": "C10",
"dia": "H25",
"shape": "IV",
"occurrence": "x-900k3",
"host": "P1-CP",
"design_length": "9816.600",
"coupler_length": "0.000",
"src": "X -900; loop 3 Y 290..1450; laps 2x750 not drawn (length only)",
"b_sched": "2998.3",
"w_model": "1160.0"
}
}
},
{
"layer": "P1::철근::코핑::C11",
"type": "Brep",
"count": 60,
"sample": {
"name": "P1-R-C11-x+5900k3",
"userstrings": {
"id": "P1-R-C11-x+5900k3",
"mark": "C11",
"dia": "H25",
"shape": "IV",
"occurrence": "x+5900k3",
"host": "P1-CP",
"design_length": "7147.819",
"coupler_length": "0.000",
"src": "X 5900; loop 3 Y 290..1450; laps 2x750 not drawn (length only)",
"b_sched": "1663.9",
"w_model": "1160.0"
}
}
},
{
"layer": "P1::철근::코핑::C12",
"type": "Brep",
"count": 18,
"sample": {
"name": "P1-R-C12-z42011k3",
"userstrings": {
"id": "P1-R-C12-z42011k3",
"mark": "C12",
"dia": "H25",
"shape": "X",
"occurrence": "z42011k3",
"host": "P1-CP",
"design_length": "28988.349",
"coupler_length": "0.000",
"src": "EL 42.011; X -6085.9..6088.0; loop 3 Y 317..1423; laps 4x580 length only",
"a_sched": "12228.2",
"w_model": "1106.0"
}
}
},
{
"layer": "P1::철근::코핑::C13",
"type": "Brep",
"count": 9,
"sample": {
"name": "P1-R-C13-z42761k3",
"userstrings": {
"id": "P1-R-C13-z42761k3",
"mark": "C13",
"dia": "H25",
"shape": "X",
"occurrence": "z42761k3",
"host": "P1-CP",
"design_length": "28620.470",
"coupler_length": "0.000",
"src": "EL 42.761; X -5985.9..6004.1; loop 3 Y 317..1423; laps 4x580 length only",
"a_sched": "12044.2",
"w_model": "1106.0"
}
}
},
{
"layer": "P1::철근::코핑::C14",
"type": "Brep",
"count": 41,
"sample": {
"name": "P1-R-C14-x+2913z43442",
"userstrings": {
"id": "P1-R-C14-x+2913z43442",
"mark": "C14",
"dia": "H19",
"shape": "III",
"occurrence": "x+2913z43442",
"host": "P1-CP",
"design_length": "3600.000",
"coupler_length": "0.000",
"src": "D1 정면도 점; hooks down [추론]"
}
}
},
{
"layer": "P1::철근::코핑::C15",
"type": "Brep",
"count": 13,
"sample": {
"name": "P1-R-C15-y+1450",
"userstrings": {
"id": "P1-R-C15-y+1450",
"mark": "C15",
"dia": "H19",
"shape": "III",
"occurrence": "y+1450",
"host": "P1-CP",
"design_length": "2784.000",
"coupler_length": "0.000",
"src": "D1 정면도 43,598.4 / 3,816~5,900"
}
}
},
{
"layer": "P1::철근::코핑::C16",
"type": "Brep",
"count": 13,
"sample": {
"name": "P1-R-C16-y+1450",
"userstrings": {
"id": "P1-R-C16-y+1450",
"mark": "C16",
"dia": "H19",
"shape": "II",
"occurrence": "y+1450",
"host": "P1-CP",
"design_length": "5611.000",
"coupler_length": "0.000",
"src": "D1 정면도 43,454.7 / -1,195~4,066; hook at left end [추론]"
}
}
},
{
"layer": "P1::철근::코핑::C2",
"type": "Brep",
"count": 12,
"sample": {
"name": "P1-R-C2-t2y+1312",
"userstrings": {
"id": "P1-R-C2-t2y+1312",
"mark": "C2",
"dia": "H29",
"shape": "VIII",
"occurrence": "t2y+1312",
"host": "P1-CP",
"design_length": "12082.000",
"coupler_length": "0.000",
"src": "tier 2 EL 43.211; end inset 100.6; legs parallel to end faces",
"a_model": "11880.000"
}
}
},
{
"layer": "P1::철근::코핑::C3",
"type": "Brep",
"count": 12,
"sample": {
"name": "P1-R-C3-t3y+1312",
"userstrings": {
"id": "P1-R-C3-t3y+1312",
"mark": "C3",
"dia": "H29",
"shape": "VIII",
"occurrence": "t3y+1312",
"host": "P1-CP",
"design_length": "12106.000",
"coupler_length": "0.000",
"src": "tier 3 EL 43.111; end inset 100.8; legs parallel to end faces",
"a_model": "11904.000"
}
}
},
{
"layer": "P1::철근::코핑::C4",
"type": "Brep",
"count": 12,
"sample": {
"name": "P1-R-C4-t1y+1450",
"userstrings": {
"id": "P1-R-C4-t1y+1450",
"mark": "C4",
"dia": "H29",
"shape": "VIII",
"occurrence": "t1y+1450",
"host": "P1-CP",
"design_length": "14489.000",
"coupler_length": "0.000",
"src": "tier 1 EL 43.311; end inset 100.8; legs parallel to end faces",
"a_model": "11855.000"
}
}
},
{
"layer": "P1::철근::코핑::C5",
"type": "Brep",
"count": 12,
"sample": {
"name": "P1-R-C5-t2y+1450",
"userstrings": {
"id": "P1-R-C5-t2y+1450",
"mark": "C5",
"dia": "H29",
"shape": "VIII",
"occurrence": "t2y+1450",
"host": "P1-CP",
"design_length": "12082.000",
"coupler_length": "0.000",
"src": "tier 2 EL 43.211; end inset 100.6; legs parallel to end faces",
"a_model": "11880.000"
}
}
},
{
"layer": "P1::철근::코핑::C6",
"type": "Brep",
"count": 12,
"sample": {
"name": "P1-R-C6-t3y+1450",
"userstrings": {
"id": "P1-R-C6-t3y+1450",
"mark": "C6",
"dia": "H29",
"shape": "VIII",
"occurrence": "t3y+1450",
"host": "P1-CP",
"design_length": "12106.000",
"coupler_length": "0.000",
"src": "tier 3 EL 43.111; end inset 100.8; legs parallel to end faces",
"a_model": "11904.000"
}
}
},
{
"layer": "P1::철근::코핑::C7",
"type": "Brep",
"count": 12,
"sample": {
"name": "P1-R-C7-y+1312",
"userstrings": {
"id": "P1-R-C7-y+1312",
"mark": "C7",
"dia": "H29",
"shape": "VII",
"occurrence": "y+1312",
"host": "P1-CP",
"design_length": "13993.991",
"coupler_length": "0.000",
"src": "flat EL 40.511 +-1,073.9; arcs R 12,100 concentric with soffit, length 5,273; legs 650 // end faces"
}
}
},
{
"layer": "P1::철근::코핑::C8",
"type": "Brep",
"count": 12,
"sample": {
"name": "P1-R-C8-y+1450",
"userstrings": {
"id": "P1-R-C8-y+1450",
"mark": "C8",
"dia": "H29",
"shape": "VII",
"occurrence": "y+1450",
"host": "P1-CP",
"design_length": "13993.991",
"coupler_length": "0.000",
"src": "flat EL 40.511 +-1,073.9; arcs R 12,100 concentric with soffit, length 5,273; legs 650 // end faces"
}
}
},
{
"layer": "P1::철근::코핑::C9",
"type": "Brep",
"count": 60,
"sample": {
"name": "P1-R-C9-x-5900k3",
"userstrings": {
"id": "P1-R-C9-x-5900k3",
"mark": "C9",
"dia": "H25",
"shape": "IV",
"occurrence": "x-5900k3",
"host": "P1-CP",
"design_length": "6573.019",
"coupler_length": "0.000",
"src": "X -5900; loop 3 Y 290..1450; laps 2x750 not drawn (length only)",
"b_sched": "1376.5",
"w_model": "1160.0"
}
}
},
{
"layer": "P1::철근::코핑::S1",
"type": "Brep",
"count": 50,
"sample": {
"name": "P1-R-S1-g5c+550",
"userstrings": {
"id": "P1-R-S1-g5c+550",
"mark": "S1",
"dia": "H19",
"shape": "III",
"occurrence": "g5c+550",
"host": "P1-CP",
"design_length": "3800.000",
"coupler_length": "0.000",
"src": "girder 5 pedestal; upper layer [추론]"
}
}
},
{
"layer": "P1::철근::코핑::S2",
"type": "Brep",
"count": 105,
"sample": {
"name": "P1-R-S2-g5a+1200",
"userstrings": {
"id": "P1-R-S2-g5a+1200",
"mark": "S2",
"dia": "H19",
"shape": "III",
"occurrence": "g5a+1200",
"host": "P1-CP",
"design_length": "2500.000",
"coupler_length": "0.000",
"src": "girder 5 pedestal; lower layer"
}
}
},
{
"layer": "P1::코핑",
"type": "Brep",
"count": 1,
"sample": {
"name": "P1-CP",
"userstrings": {
"id": "P1-CP",
"role": "coping",
"fck": "40MPa",
"source_views": "D1 평면도, D1 정면도, D1 단면도, D1 단면 A-A/B-B"
}
}
}
]
}
+250
View File
@@ -0,0 +1,250 @@
{
"ungok": {
"folder": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\철근 모델랑 운곡교P1_바이브코딩",
"reviewed_copy": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\철근 모델랑 운곡교P1_바이브코딩\\운곡교p1_검토완료.3dm",
"objects_before": 3236,
"short_before": {
"other": 1247,
"footing": 328
},
"stat": {
"replaced": 390,
"held_footing": 155,
"skipped_complex": 72
},
"per_mark": {
"S2/H19": {
"bars": 105,
"sum_dlen_mm": -16.224
},
"S1/H19": {
"bars": 50,
"sum_dlen_mm": -7.726
},
"C16/H19": {
"bars": 13,
"sum_dlen_mm": -1.004
},
"C15/H19": {
"bars": 13,
"sum_dlen_mm": -2.009
},
"C14/H19": {
"bars": 41,
"sum_dlen_mm": -6.335
},
"C13/H25": {
"bars": 9,
"sum_dlen_mm": -10.816
},
"C12/H25": {
"bars": 18,
"sum_dlen_mm": -21.632
},
"C9/H25": {
"bars": 60,
"sum_dlen_mm": -72.106
},
"C11/H25": {
"bars": 60,
"sum_dlen_mm": -72.106
},
"C10/H25": {
"bars": 21,
"sum_dlen_mm": -25.237
}
},
"short_after": {
"footing": 328,
"other": 144
},
"objects_after": 3236,
"saved": true,
"out": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\철근 모델랑 운곡교P1_바이브코딩\\운곡교p1_수정_20261023.3dm"
},
"sanoe": {
"folder": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\검토_산외교P1",
"reviewed_copy": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\검토_산외교P1\\산외교P1 G5_검토완료.3dm",
"objects_before": 2004,
"short_before": {
"other": 674,
"footing": 124
},
"stat": {
"replaced": 207,
"held_footing": 62
},
"per_mark": {
"C7/H22": {
"bars": 51,
"sum_dlen_mm": -30.645
},
"C10/H22": {
"bars": 7,
"sum_dlen_mm": -4.206
},
"C9/H22": {
"bars": 51,
"sum_dlen_mm": -30.645
},
"C8/H22": {
"bars": 21,
"sum_dlen_mm": -12.619
},
"C15/H22": {
"bars": 13,
"sum_dlen_mm": -3.212
},
"P5/H19": {
"bars": 64,
"sum_dlen_mm": -9.889
}
},
"short_after": {
"footing": 124
},
"objects_after": 2004,
"saved": true,
"out": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\검토_산외교P1\\산외교P1 G5_수정_20261023.3dm"
},
"okseong": {
"folder": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\검토_옥성교P1",
"reviewed_copy": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\검토_옥성교P1\\옥성교P1_G5_검토완료.3dm",
"objects_before": 3862,
"short_before": {
"other": 1949,
"footing": 780
},
"stat": {
"replaced": 561,
"skipped_pipe_fail": 18,
"held_footing": 214
},
"per_mark": {
"S2/H19": {
"bars": 21,
"sum_dlen_mm": -3.245
},
"S1/H19": {
"bars": 11,
"sum_dlen_mm": -1.7
},
"C18/H19": {
"bars": 117,
"sum_dlen_mm": -17.24
},
"C14/H22": {
"bars": 6,
"sum_dlen_mm": -4.47
},
"C16/H22": {
"bars": 6,
"sum_dlen_mm": -4.47
},
"C13/H25": {
"bars": 72,
"sum_dlen_mm": -76.003
},
"C12/H25": {
"bars": 40,
"sum_dlen_mm": -48.071
},
"C11/H25": {
"bars": 54,
"sum_dlen_mm": -57.013
},
"C10/H25": {
"bars": 27,
"sum_dlen_mm": -32.448
},
"C9/H25": {
"bars": 68,
"sum_dlen_mm": -72.086
},
"C8/H25": {
"bars": 39,
"sum_dlen_mm": -46.869
},
"C20/H19": {
"bars": 75,
"sum_dlen_mm": -5.794
},
"C19/H19": {
"bars": 25,
"sum_dlen_mm": -3.863
}
},
"short_after": {
"other": 90,
"footing": 780
},
"objects_after": 3862,
"saved": true,
"out": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\검토_옥성교P1\\옥성교P1_G5_수정_20261023.3dm"
},
"rampa": {
"folder": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\Ramp-A교P1",
"reviewed_copy": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\Ramp-A교P1\\ramp-A G5_검토완료.3dm",
"objects_before": 2255,
"short_before": {
"other": 1040
},
"stat": {
"replaced": 260,
"skipped_pipe_fail": 12
},
"per_mark": {
"C15/H19": {
"bars": 51,
"sum_dlen_mm": -7.88
},
"C16/H19": {
"bars": 17,
"sum_dlen_mm": -2.627
},
"C13/H19": {
"bars": 18,
"sum_dlen_mm": -5.562
},
"C14/H19": {
"bars": 12,
"sum_dlen_mm": -3.708
},
"C12/H19": {
"bars": 28,
"sum_dlen_mm": -8.207
},
"C11/H19": {
"bars": 20,
"sum_dlen_mm": -6.181
},
"C10/H19": {
"bars": 30,
"sum_dlen_mm": -8.934
},
"C9/H19": {
"bars": 15,
"sum_dlen_mm": -4.635
},
"C8/H19": {
"bars": 40,
"sum_dlen_mm": -11.781
},
"C7/H19": {
"bars": 20,
"sum_dlen_mm": -6.181
},
"C3/H25": {
"bars": 9,
"sum_dlen_mm": -2.973
}
},
"short_after": {
"other": 60
},
"objects_after": 2255,
"saved": true,
"out": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\Ramp-A교P1\\ramp-A G5_수정_20261023.3dm"
},
"done": true
}
+23
View File
@@ -0,0 +1,23 @@
{
"objects_before": 3236,
"stat": {
"replaced": 493
},
"length_old": [
2144.7,
2144.7
],
"length_new": [
2256.1,
2256.1
],
"total_len_old_m": 1057.34,
"total_len_new_m": 1112.26,
"pipe_top_z_rel": 2154.5,
"footing_top_z_rel": 2200.0,
"min_cover_above_hook": 45.5,
"objects_after": 3236,
"saved": true,
"out": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\철근 모델랑 운곡교P1_바이브코딩\\운곡교p1_수정6_20261026.3dm",
"done": true
}
@@ -0,0 +1,25 @@
{
"counts": {
"fix_attr": 986,
"curve": 493
},
"arcs": {
"[(24.0, 90.0), (45.0, 180.0)]": 493
},
"last_segment": {
"100.0 nseg=5": 493
},
"lengths": {
"2322.1": 493
},
"layers": {
"P1::철근::기초::B9|layer_on": 493,
"P1::철근::중심선|layer_on": 493
},
"strings": {
"수정일": "2026-10-26",
"수정내용": "C-1 bend radius to KDS 24 14 21 Table 4.5-1 (footing bars held, P3 rings / complex bars not changed) | footing: B5 z2100, B6/B8 z150, B1 z2072.5, B2/B4 z177 (B2 legs end 2072.5), C-1 R for B1,B2,B3,B7,B10; B9 untouched | B9 top hook R45 + extension 100 (assumed, user 2026-10-26, replaces R65/150 version)"
},
"objects": 3236,
"done": true
}
@@ -0,0 +1,25 @@
{
"counts": {
"fix_attr": 986,
"curve": 493
},
"arcs": {
"[(24.0, 90.0), (24.0, 180.0)]": 493
},
"last_segment": {
"100.0 nseg=5": 493
},
"lengths": {
"2256.1": 493
},
"layers": {
"P1::철근::기초::B9|layer_on": 493,
"P1::철근::중심선|layer_on": 493
},
"strings": {
"수정일": "2026-10-26",
"수정내용": "C-1 bend radius to KDS 24 14 21 Table 4.5-1 (footing bars held, P3 rings / complex bars not changed) | footing: B5 z2100, B6/B8 z150, B1 z2072.5, B2/B4 z177 (B2 legs end 2072.5), C-1 R for B1,B2,B3,B7,B10; B9 untouched | B9 top hook R24 (KDS min for H16 23.85, rounded up like other H16 bends) + extension 100 (user 2026-10-26, replaces R65/R45 versions)"
},
"objects": 3236,
"done": true
}
@@ -0,0 +1,305 @@
{
"ungok": {
"P3": {
"bars": 72,
"plan_status": {
"complex": 72
},
"orig_pipe_ok": 72,
"orig_pipe_fail": 0,
"new_pipe_ok": 0,
"new_pipe_fail": 0,
"sample": {
"name": "P1-RC-P3-L67b",
"flag": "ok",
"valid": true,
"segs": [
[
"LineCurve",
86.67,
null,
null
],
[
"ArcCurve",
106.27,
42.75,
142.42
],
[
"ArcCurve",
2585.58,
897.0,
165.15
],
[
"ArcCurve",
106.27,
42.75,
142.42
],
[
"LineCurve",
86.67,
null,
null
]
]
}
}
},
"okseong": {
"C13": {
"bars": 8,
"plan_status": {
"ok": 8
},
"orig_pipe_ok": 0,
"orig_pipe_fail": 8,
"new_pipe_ok": 0,
"new_pipe_fail": 8,
"sample": {
"name": "P1-RC-C13-x+3475L",
"flag": "fail",
"valid": true,
"segs": [
[
"PolylineCurve",
758.63,
null,
null
],
[
"ArcCurve",
88.36,
56.25,
90.0
],
[
"PolylineCurve",
1335.51,
null,
null
],
[
"ArcCurve",
15.37,
56.25,
15.66
],
[
"PolylineCurve",
704.95,
null,
null
],
[
"ArcCurve",
72.98,
56.25,
74.34
],
[
"PolylineCurve",
774.96,
null,
null
],
[
"ArcCurve",
88.36,
56.25,
90.0
],
[
"PolylineCurve",
2014.3,
null,
null
],
[
"ArcCurve",
88.36,
56.25,
90.0
],
[
"PolylineCurve",
206.62,
null,
null
]
]
}
},
"C9": {
"bars": 10,
"plan_status": {
"ok": 10
},
"orig_pipe_ok": 0,
"orig_pipe_fail": 10,
"new_pipe_ok": 0,
"new_pipe_fail": 10,
"sample": {
"name": "P1-RC-C9-x-3225L",
"flag": "fail",
"valid": true,
"segs": [
[
"PolylineCurve",
758.63,
null,
null
],
[
"ArcCurve",
88.36,
56.25,
90.0
],
[
"PolylineCurve",
1355.71,
null,
null
],
[
"ArcCurve",
15.37,
56.25,
15.66
],
[
"PolylineCurve",
788.66,
null,
null
],
[
"ArcCurve",
72.98,
56.25,
74.34
],
[
"PolylineCurve",
752.37,
null,
null
],
[
"ArcCurve",
88.36,
56.25,
90.0
],
[
"PolylineCurve",
2115.1,
null,
null
],
[
"ArcCurve",
88.36,
56.25,
90.0
],
[
"PolylineCurve",
206.62,
null,
null
]
]
}
}
},
"rampa": {
"C12": {
"bars": 12,
"plan_status": {
"ok": 12
},
"orig_pipe_ok": 0,
"orig_pipe_fail": 12,
"new_pipe_ok": 0,
"new_pipe_fail": 12,
"sample": {
"name": "P1-RC-C12-x+2500L",
"flag": "fail",
"valid": true,
"segs": [
[
"PolylineCurve",
269.75,
null,
null
],
[
"ArcCurve",
67.15,
42.75,
90.0
],
[
"PolylineCurve",
1190.03,
null,
null
],
[
"ArcCurve",
2.84,
42.75,
3.81
],
[
"PolylineCurve",
286.7,
null,
null
],
[
"ArcCurve",
64.31,
42.75,
86.19
],
[
"PolylineCurve",
520.44,
null,
null
],
[
"ArcCurve",
67.15,
42.75,
90.0
],
[
"PolylineCurve",
1476.09,
null,
null
],
[
"ArcCurve",
67.15,
42.75,
90.0
],
[
"PolylineCurve",
269.75,
null,
null
]
]
}
}
},
"done": true
}
+595
View File
@@ -0,0 +1,595 @@
{
"ungok": {
"objects": 3236,
"marks": [
{
"mark": "S2",
"dia": "H19",
"req": 42.93,
"bars": 105,
"short_bars": 105,
"short_arcs": 210,
"ok": 105,
"sum_dlen_x1000": -16275,
"max_dlen_x1000": 155
},
{
"mark": "S1",
"dia": "H19",
"req": 42.93,
"bars": 50,
"short_bars": 50,
"short_arcs": 100,
"ok": 50,
"sum_dlen_x1000": -7750,
"max_dlen_x1000": 155
},
{
"mark": "C16",
"dia": "H19",
"req": 42.93,
"bars": 13,
"short_bars": 13,
"short_arcs": 13,
"ok": 13,
"sum_dlen_x1000": -1001,
"max_dlen_x1000": 77
},
{
"mark": "C15",
"dia": "H19",
"req": 42.93,
"bars": 13,
"short_bars": 13,
"short_arcs": 26,
"ok": 13,
"sum_dlen_x1000": -2015,
"max_dlen_x1000": 155
},
{
"mark": "C14",
"dia": "H19",
"req": 42.93,
"bars": 41,
"short_bars": 41,
"short_arcs": 82,
"ok": 41,
"sum_dlen_x1000": -6355,
"max_dlen_x1000": 155
},
{
"mark": "C13",
"dia": "H25",
"req": 56.95,
"bars": 9,
"short_bars": 9,
"short_arcs": 36,
"ok": 9,
"sum_dlen_x1000": -10818,
"max_dlen_x1000": 1202
},
{
"mark": "C12",
"dia": "H25",
"req": 56.95,
"bars": 18,
"short_bars": 18,
"short_arcs": 72,
"ok": 18,
"sum_dlen_x1000": -21636,
"max_dlen_x1000": 1202
},
{
"mark": "C9",
"dia": "H25",
"req": 56.95,
"bars": 60,
"short_bars": 60,
"short_arcs": 240,
"ok": 60,
"sum_dlen_x1000": -72120,
"max_dlen_x1000": 1202
},
{
"mark": "C11",
"dia": "H25",
"req": 56.95,
"bars": 60,
"short_bars": 60,
"short_arcs": 240,
"ok": 60,
"sum_dlen_x1000": -72120,
"max_dlen_x1000": 1202
},
{
"mark": "C10",
"dia": "H25",
"req": 56.95,
"bars": 21,
"short_bars": 21,
"short_arcs": 84,
"ok": 21,
"sum_dlen_x1000": -25242,
"max_dlen_x1000": 1202
},
{
"mark": "B10",
"dia": "S19",
"req": 42.93,
"bars": 9,
"short_bars": 9,
"short_arcs": 36,
"ok": 9,
"sum_dlen_x1000": -2781,
"max_dlen_x1000": 309
},
{
"mark": "B1",
"dia": "S25",
"req": 56.95,
"bars": 38,
"short_bars": 38,
"short_arcs": 76,
"ok": 38,
"sum_dlen_x1000": -22838,
"max_dlen_x1000": 601
},
{
"mark": "B7",
"dia": "S19",
"req": 42.93,
"bars": 32,
"short_bars": 32,
"short_arcs": 64,
"ok": 32,
"sum_dlen_x1000": -4960,
"max_dlen_x1000": 155
},
{
"mark": "B3",
"dia": "S19",
"req": 42.93,
"bars": 38,
"short_bars": 38,
"short_arcs": 76,
"ok": 38,
"sum_dlen_x1000": -5890,
"max_dlen_x1000": 155
},
{
"mark": "B2",
"dia": "S25",
"req": 56.95,
"bars": 38,
"short_bars": 38,
"short_arcs": 76,
"ok": 38,
"sum_dlen_x1000": -22838,
"max_dlen_x1000": 601
},
{
"mark": "P3",
"dia": "H19",
"req": 42.93,
"bars": 72,
"short_bars": 72,
"short_arcs": 144,
"complex": 72
}
]
},
"sanoe": {
"objects": 2004,
"marks": [
{
"mark": "C7",
"dia": "H22",
"req": 49.85,
"bars": 51,
"short_bars": 51,
"short_arcs": 204,
"ok": 51,
"sum_dlen_x1000": -30651,
"max_dlen_x1000": 601
},
{
"mark": "C10",
"dia": "H22",
"req": 49.85,
"bars": 7,
"short_bars": 7,
"short_arcs": 28,
"ok": 7,
"sum_dlen_x1000": -4207,
"max_dlen_x1000": 601
},
{
"mark": "C9",
"dia": "H22",
"req": 49.85,
"bars": 51,
"short_bars": 51,
"short_arcs": 204,
"ok": 51,
"sum_dlen_x1000": -30651,
"max_dlen_x1000": 601
},
{
"mark": "C8",
"dia": "H22",
"req": 49.85,
"bars": 21,
"short_bars": 21,
"short_arcs": 84,
"ok": 21,
"sum_dlen_x1000": -12621,
"max_dlen_x1000": 601
},
{
"mark": "C15",
"dia": "H22",
"req": 49.85,
"bars": 13,
"short_bars": 13,
"short_arcs": 26,
"ok": 13,
"sum_dlen_x1000": -3211,
"max_dlen_x1000": 247
},
{
"mark": "B5",
"dia": "H22",
"req": 49.85,
"bars": 31,
"short_bars": 31,
"short_arcs": 62,
"ok": 31,
"sum_dlen_x1000": -9300,
"max_dlen_x1000": 300
},
{
"mark": "B2",
"dia": "H22",
"req": 49.85,
"bars": 31,
"short_bars": 31,
"short_arcs": 62,
"ok": 31,
"sum_dlen_x1000": -9300,
"max_dlen_x1000": 300
},
{
"mark": "P5",
"dia": "H19",
"req": 42.93,
"bars": 64,
"short_bars": 64,
"short_arcs": 128,
"ok": 64,
"sum_dlen_x1000": -9920,
"max_dlen_x1000": 155
}
]
},
"okseong": {
"objects": 3862,
"marks": [
{
"mark": "S2",
"dia": "H19",
"req": 42.93,
"bars": 21,
"short_bars": 21,
"short_arcs": 42,
"ok": 21,
"sum_dlen_x1000": -3255,
"max_dlen_x1000": 155
},
{
"mark": "S1",
"dia": "H19",
"req": 42.93,
"bars": 11,
"short_bars": 11,
"short_arcs": 22,
"ok": 11,
"sum_dlen_x1000": -1705,
"max_dlen_x1000": 155
},
{
"mark": "C18",
"dia": "H19",
"req": 42.93,
"bars": 117,
"short_bars": 117,
"short_arcs": 234,
"ok": 117,
"sum_dlen_x1000": -17287,
"max_dlen_x1000": 79
},
{
"mark": "C14",
"dia": "H22",
"req": 49.85,
"bars": 6,
"short_bars": 6,
"short_arcs": 24,
"ok": 6,
"sum_dlen_x1000": -4470,
"max_dlen_x1000": 745
},
{
"mark": "C16",
"dia": "H22",
"req": 49.85,
"bars": 6,
"short_bars": 6,
"short_arcs": 24,
"ok": 6,
"sum_dlen_x1000": -4470,
"max_dlen_x1000": 745
},
{
"mark": "C13",
"dia": "H25",
"req": 56.95,
"bars": 80,
"short_bars": 80,
"short_arcs": 396,
"ok": 72,
"sum_dlen_x1000": -76018,
"max_dlen_x1000": 1202,
"pipe_fail": 8
},
{
"mark": "C12",
"dia": "H25",
"req": 56.95,
"bars": 40,
"short_bars": 40,
"short_arcs": 160,
"ok": 40,
"sum_dlen_x1000": -48080,
"max_dlen_x1000": 1202
},
{
"mark": "C11",
"dia": "H25",
"req": 56.95,
"bars": 54,
"short_bars": 54,
"short_arcs": 270,
"ok": 54,
"sum_dlen_x1000": -57024,
"max_dlen_x1000": 1056
},
{
"mark": "C10",
"dia": "H25",
"req": 56.95,
"bars": 27,
"short_bars": 27,
"short_arcs": 108,
"ok": 27,
"sum_dlen_x1000": -32454,
"max_dlen_x1000": 1202
},
{
"mark": "C9",
"dia": "H25",
"req": 56.95,
"bars": 78,
"short_bars": 78,
"short_arcs": 388,
"ok": 68,
"sum_dlen_x1000": -72100,
"max_dlen_x1000": 1056,
"pipe_fail": 10
},
{
"mark": "C8",
"dia": "H25",
"req": 56.95,
"bars": 39,
"short_bars": 39,
"short_arcs": 156,
"ok": 39,
"sum_dlen_x1000": -46878,
"max_dlen_x1000": 1202
},
{
"mark": "C20",
"dia": "H19",
"req": 42.93,
"bars": 75,
"short_bars": 75,
"short_arcs": 75,
"ok": 75,
"sum_dlen_x1000": -5775,
"max_dlen_x1000": 77
},
{
"mark": "C19",
"dia": "H19",
"req": 42.93,
"bars": 25,
"short_bars": 25,
"short_arcs": 50,
"ok": 25,
"sum_dlen_x1000": -3875,
"max_dlen_x1000": 155
},
{
"mark": "B10",
"dia": "H19",
"req": 42.93,
"bars": 5,
"short_bars": 5,
"short_arcs": 20,
"ok": 5,
"sum_dlen_x1000": -1545,
"max_dlen_x1000": 309
},
{
"mark": "B9",
"dia": "H19",
"req": 42.93,
"bars": 171,
"short_bars": 171,
"short_arcs": 684,
"ok": 171,
"sum_dlen_x1000": -52839,
"max_dlen_x1000": 309
},
{
"mark": "B11",
"dia": "H19",
"req": 42.93,
"bars": 19,
"short_bars": 19,
"short_arcs": 38,
"ok": 19,
"sum_dlen_x1000": -2945,
"max_dlen_x1000": 155
},
{
"mark": "B12",
"dia": "H19",
"req": 42.93,
"bars": 19,
"short_bars": 19,
"short_arcs": 38,
"ok": 19,
"sum_dlen_x1000": -2945,
"max_dlen_x1000": 155
}
]
},
"rampa": {
"objects": 2255,
"marks": [
{
"mark": "C15",
"dia": "H19",
"req": 42.93,
"bars": 51,
"short_bars": 51,
"short_arcs": 102,
"ok": 51,
"sum_dlen_x1000": -7905,
"max_dlen_x1000": 155
},
{
"mark": "C16",
"dia": "H19",
"req": 42.93,
"bars": 17,
"short_bars": 17,
"short_arcs": 34,
"ok": 17,
"sum_dlen_x1000": -2635,
"max_dlen_x1000": 155
},
{
"mark": "C13",
"dia": "H19",
"req": 42.93,
"bars": 18,
"short_bars": 18,
"short_arcs": 72,
"ok": 18,
"sum_dlen_x1000": -5562,
"max_dlen_x1000": 309
},
{
"mark": "C14",
"dia": "H19",
"req": 42.93,
"bars": 12,
"short_bars": 12,
"short_arcs": 48,
"ok": 12,
"sum_dlen_x1000": -3708,
"max_dlen_x1000": 309
},
{
"mark": "C12",
"dia": "H19",
"req": 42.93,
"bars": 40,
"short_bars": 40,
"short_arcs": 198,
"ok": 28,
"sum_dlen_x1000": -8212,
"max_dlen_x1000": 232,
"pipe_fail": 12
},
{
"mark": "C11",
"dia": "H19",
"req": 42.93,
"bars": 20,
"short_bars": 20,
"short_arcs": 80,
"ok": 20,
"sum_dlen_x1000": -6180,
"max_dlen_x1000": 309
},
{
"mark": "C10",
"dia": "H19",
"req": 42.93,
"bars": 30,
"short_bars": 30,
"short_arcs": 150,
"ok": 30,
"sum_dlen_x1000": -8940,
"max_dlen_x1000": 298
},
{
"mark": "C9",
"dia": "H19",
"req": 42.93,
"bars": 15,
"short_bars": 15,
"short_arcs": 60,
"ok": 15,
"sum_dlen_x1000": -4635,
"max_dlen_x1000": 309
},
{
"mark": "C8",
"dia": "H19",
"req": 42.93,
"bars": 40,
"short_bars": 40,
"short_arcs": 198,
"ok": 40,
"sum_dlen_x1000": -11788,
"max_dlen_x1000": 298
},
{
"mark": "C7",
"dia": "H19",
"req": 42.93,
"bars": 20,
"short_bars": 20,
"short_arcs": 80,
"ok": 20,
"sum_dlen_x1000": -6180,
"max_dlen_x1000": 309
},
{
"mark": "C3",
"dia": "H25",
"req": 56.95,
"bars": 9,
"short_bars": 9,
"short_arcs": 18,
"ok": 9,
"sum_dlen_x1000": -2972,
"max_dlen_x1000": 366
}
]
}
}
@@ -0,0 +1,20 @@
{
"rampa": {
"objects_before": 2255,
"short_before": {
"C12": 60
},
"stat": {
"C12_plan_unchanged": 28,
"C12_done": 12
},
"pipe_settings": {
"fit=False atol=0.001": 12
},
"short_after": {},
"objects_after": 2255,
"saved": true,
"out": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\Ramp-A교P1\\ramp-A G5_수정2_20261026.3dm"
},
"done": true
}
@@ -0,0 +1,47 @@
{
"ungok": {
"objects_before": 3236,
"short_before": {
"P3": 144
},
"stat": {
"B2_done": 38,
"P3_done": 72
},
"pipe_settings": {
"fit=True atol=0.001": 110
},
"end_shift_mm": {
"max": 0.61,
"mean": 0.61
},
"short_after": {},
"objects_after": 3236,
"saved": true,
"out": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\철근 모델랑 운곡교P1_바이브코딩\\운곡교p1_수정7_20261026.3dm"
},
"okseong": {
"objects_before": 3862,
"short_before": {
"C13": 40,
"C9": 50
},
"stat": {
"C9_plan_unchanged": 68,
"C13_plan_unchanged": 72,
"C13_done": 8,
"C9_done": 10
},
"pipe_settings": {
"fit=False atol=0.001": 18
},
"short_after": {},
"objects_after": 3862,
"saved": true,
"out": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\검토_옥성교P1\\옥성교P1_G5_수정4_20261026.3dm"
},
"rampa": {
"error": "Traceback (most recent call last):\n File \"C:\\Users\\User\\AppData\\Local\\PierApp\\jobs\\c1_work\\c1_fix_remaining.py\", line 180, in <module>\n res[key] = run_one(key, job)\n File \"C:\\Users\\User\\AppData\\Local\\PierApp\\jobs\\c1_work\\c1_fix_remaining.py\", line 87, in run_one\n fbot = [o for o in doc.Objects.GetObjectList(st) if o.Attributes.Name == \"P1-FT\"][0].Geometry.GetBoundingBox(True).Min.Z\nIndexError: list index out of range\n"
},
"done": true
}
@@ -0,0 +1,125 @@
{
"sanoe": {
"objects_before": 2004,
"z_after_rel": {
"B1": [
2400.0,
2400.0
],
"B2": [
150.0,
2400.0
],
"B3": [
150.0,
150.0
],
"B4": [
2384.0,
2384.0
],
"B5": [
172.0,
2400.0
],
"B6": [
172.0,
172.0
],
"B7": [
166.0,
2384.0
],
"B8": [
375.0,
2175.0
],
"B10": [
1175.0,
1275.0
],
"B9": [
1175.0,
1275.0
]
},
"stat": {
"B3_done": 28,
"B6_done": 28,
"B5_done": 31,
"B4_done": 31,
"B2_done": 31,
"B1_done": 31
},
"objects_after": 2004,
"saved": true,
"out": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\검토_산외교P1\\산외교P1 G5_수정2_20261023.3dm"
},
"okseong": {
"objects_before": 3862,
"z_after_rel": {
"B6": [
179.0,
2100.0
],
"B8": [
179.0,
2100.0
],
"B5": [
1096.0,
2071.0
],
"B7": [
1096.0,
2071.0
],
"B12": [
569.0,
1669.0
],
"B11": [
550.0,
1650.0
],
"B10": [
400.0,
1900.0
],
"B9": [
126.0,
2124.0
],
"B1": [
1200.0,
2100.0
],
"B3": [
1200.0,
2100.0
],
"B2": [
150.0,
1950.0
],
"B4": [
150.0,
1950.0
]
},
"stat": {
"B10_done": 5,
"B9_done": 171,
"B11_done": 19,
"B12_done": 19,
"B5_done": 38,
"B7_done": 37,
"B6_done": 38,
"B8_done": 37
},
"objects_after": 3862,
"saved": true,
"out": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\검토_옥성교P1\\옥성교P1_G5_수정2_20261023.3dm"
},
"done": true
}
@@ -0,0 +1,121 @@
{
"objects_before": 3236,
"footing_bottom_z": 26208.0,
"z_before": {
"B9": [
26335.5,
28350.87
],
"B10": [
26558.0,
28158.0
],
"B12": [
26658.0,
27958.0
],
"B11": [
26658.0,
27958.0
],
"B5": [
28135.0,
28335.0
],
"B1": [
28081.0,
28281.0
],
"B7": [
26485.0,
26685.0
],
"B3": [
26435.5,
26635.5
],
"B6": [
26386.0,
28336.0
],
"B8": [
26386.0,
26386.0
],
"B2": [
26330.0,
28280.0
],
"B4": [
26330.0,
26330.0
]
},
"z_after": {
"B4": [
26358.0,
26358.0
],
"B2": [
26358.0,
28308.0
],
"B8": [
26358.0,
26358.0
],
"B6": [
26358.0,
28308.0
],
"B3": [
26435.5,
26635.5
],
"B7": [
26485.0,
26685.0
],
"B1": [
28108.0,
28308.0
],
"B5": [
28108.0,
28308.0
],
"B10": [
26558.0,
28158.0
],
"B9": [
26335.5,
28350.87
],
"B12": [
26658.0,
27958.0
],
"B11": [
26658.0,
27958.0
]
},
"stat": {
"B10_rfix": 9,
"B5_shift": 32,
"B1_rfix": 38,
"B1_shift": 38,
"B7_rfix": 32,
"B3_rfix": 38,
"B6_shift": 32,
"B8_shift": 29,
"B2_rfix": 38,
"B2_shift": 38,
"B4_shift": 35
},
"objects_after": 3236,
"saved": true,
"out": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\철근 모델랑 운곡교P1_바이브코딩\\운곡교p1_수정2_20261023.3dm",
"done": true
}
@@ -0,0 +1,68 @@
{
"objects_before": 3236,
"z_after_rel": {
"B2": [
177.0,
2072.5
],
"B4": [
177.0,
177.0
],
"B6": [
150.0,
2100.0
],
"B8": [
150.0,
150.0
],
"B3": [
227.5,
427.5
],
"B7": [
277.0,
477.0
],
"B1": [
1872.5,
2072.5
],
"B5": [
1900.0,
2100.0
],
"B10": [
350.0,
1950.0
],
"B9": [
127.5,
2142.87
],
"B12": [
450.0,
1750.0
],
"B11": [
450.0,
1750.0
]
},
"stat": {
"B10_done": 9,
"B5_done": 32,
"B1_done": 38,
"B7_done": 32,
"B3_done": 38,
"B6_done": 32,
"B8_done": 29,
"B2_done": 38,
"B4_done": 35
},
"objects_after": 3236,
"saved": true,
"out": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\철근 모델랑 운곡교P1_바이브코딩\\운곡교p1_수정3_20261023.3dm",
"done": true
}
+539
View File
@@ -0,0 +1,539 @@
{
"sanoe": {
"footing_solids": [
[
"P1-FT",
"P1::기초",
[
-3750.0,
-3750.0,
42763.0,
3750.0,
3750.0,
45263.0
]
]
],
"layers": [
"P1::기초",
"P1::철근::기초",
"P1::철근::기초::B1",
"P1::철근::기초::B10",
"P1::철근::기초::B2",
"P1::철근::기초::B3",
"P1::철근::기초::B4",
"P1::철근::기초::B5",
"P1::철근::기초::B6",
"P1::철근::기초::B7",
"P1::철근::기초::B8",
"P1::철근::기초::B9"
],
"marks": {
"B7": {
"dia": "H13",
"shape": "I",
"host": "P1-FT",
"n": 98,
"mn": [
-3250.0,
-3250.0,
42929.0
],
"mx": [
3250.0,
3350.0,
45147.0
],
"src": "14x14 격자 @500 중 체크무늬 98 [추론]; 작도 z 150~2,400, A 중앙 배치 [추론]; 갈고리 +Y [추론]",
"design_length": "2418.000",
"zr_samples": {
"42929.0..45147.0": 98
}
},
"B3": {
"dia": "H22",
"shape": "I",
"host": "P1-FT",
"n": 28,
"mn": [
-3375.0,
-3650.0,
42890.5
],
"mx": [
3375.0,
3650.0,
42890.5
],
"src": "배근도(1) 정면도 기초 하면 '56@125' 중 B2 외",
"design_length": "7300.000",
"zr_samples": {
"42890.5..42890.5": 28
}
},
"B8": {
"dia": "H16",
"shape": "V",
"host": "P1-FT",
"n": 7,
"mn": [
-3672.5,
-3672.5,
43138.0
],
"mx": [
3672.5,
3672.5,
44938.0
],
"src": "정면·측면 둘레 띠 ±3,672.5, z 375~2,175 @300; 길이 2A+2B+4J",
"design_length": "31580.000",
"zr_samples": {
"44938.0..44938.0": 1,
"44638.0..44638.0": 1,
"44338.0..44338.0": 1,
"44038.0..44038.0": 1
}
},
"B10": {
"dia": "H16",
"shape": "III",
"host": "P1-FT",
"n": 7,
"mn": [
-3250.0,
-3650.0,
43938.0
],
"mx": [
2750.0,
3650.0,
44038.0
],
"src": "배근도(1) 정면도 기초 중앙 (작도 위치, 비대칭; B9와 같은 높이)",
"design_length": "7500.000",
"zr_samples": {
"43938.0..44038.0": 7
}
},
"B9": {
"dia": "H16",
"shape": "III",
"host": "P1-FT",
"n": 7,
"mn": [
-3650.0,
-3250.0,
43938.0
],
"mx": [
3650.0,
2750.0,
44038.0
],
"src": "배근도(1) 측면도 기초 중앙 (작도 위치, 비대칭)",
"design_length": "7500.000",
"zr_samples": {
"43938.0..44038.0": 7
}
},
"B6": {
"dia": "H22",
"shape": "I",
"host": "P1-FT",
"n": 28,
"mn": [
-3650.0,
-3375.0,
42935.5
],
"mx": [
3650.0,
3375.0,
42935.5
],
"src": "배근도(1) 측면도 기초 하면 B5 외",
"design_length": "7300.000",
"zr_samples": {
"42935.5..42935.5": 28
}
},
"B5": {
"dia": "H22",
"shape": "IV",
"host": "P1-FT",
"n": 31,
"mn": [
-3650.0,
-3650.0,
42935.5
],
"mx": [
3650.0,
3600.0,
45185.5
],
"src": "배근도(1) 측면도 기초 하면 U형 (정면 상면 위치) [추론]",
"design_length": "12800.000",
"zr_samples": {
"42935.5..45185.5": 31
}
},
"B4": {
"dia": "H16",
"shape": "I",
"host": "P1-FT",
"n": 31,
"mn": [
-3650.0,
-3650.0,
45140.5
],
"mx": [
3650.0,
3650.0,
45140.5
],
"src": "배근도(1) 측면도 기초 상면 사슬 (끝 '150','100' -> 3,650, 정면과 불일치)",
"design_length": "7300.000",
"zr_samples": {
"45140.5..45140.5": 31
}
},
"B2": {
"dia": "H22",
"shape": "IV",
"host": "P1-FT",
"n": 31,
"mn": [
-3650.0,
-3650.0,
42890.5
],
"mx": [
3600.0,
3650.0,
45140.5
],
"src": "배근도(1) 정면도 기초 하면 U형 (상면 위치), 이음 J 1000 길이만",
"design_length": "12800.000",
"zr_samples": {
"42890.5..45140.5": 31
}
},
"B1": {
"dia": "H16",
"shape": "I",
"host": "P1-FT",
"n": 31,
"mn": [
-3650.0,
-3650.0,
45185.5
],
"mx": [
3600.0,
3650.0,
45185.5
],
"src": "배근도(1) 정면도 기초 상면 사슬 '28@250' (끝 3,600)",
"design_length": "7300.000",
"zr_samples": {
"45185.5..45185.5": 31
}
}
}
},
"okseong": {
"footing_solids": [
[
"P1-FT",
"P1::기초",
[
-4800.0,
-4800.0,
12175.0,
4800.0,
4800.0,
14375.0
]
]
],
"layers": [
"P1::기초",
"P1::철근::기초",
"P1::철근::기초::B1",
"P1::철근::기초::B10",
"P1::철근::기초::B11",
"P1::철근::기초::B12",
"P1::철근::기초::B2",
"P1::철근::기초::B3",
"P1::철근::기초::B4",
"P1::철근::기초::B5",
"P1::철근::기초::B6",
"P1::철근::기초::B7",
"P1::철근::기초::B8",
"P1::철근::기초::B9"
],
"marks": {
"B10": {
"dia": "H19",
"shape": "loop",
"host": "P1-FT",
"n": 5,
"mn": [
-4722.5,
-4722.5,
12575.0
],
"mx": [
4722.5,
4722.5,
14075.0
],
"src": "정면·측면 모서리 점, 재료표 9,448 x 9,448, 겹이음 560 x 6 미모델",
"design_length": "41152.000",
"zr_samples": {
"12575.0..12575.0": 1,
"14075.0..14075.0": 1,
"13825.0..13825.0": 1,
"13325.0..13325.0": 1
}
},
"B1": {
"dia": "H29",
"shape": "U",
"host": "P1-FT",
"n": 39,
"mn": [
-4700.0,
-4700.0,
13375.0
],
"mx": [
4700.0,
4700.0,
14275.0
],
"src": "정면 상면 점 EL 14.275, 측면 다리 900; B1/B3 교번, 겹이음 j 미모델 (F3 [추론])",
"design_length": "12730.000",
"zr_samples": {
"13375.0..14275.0": 39
}
},
"B9": {
"dia": "H19",
"shape": "tie-C",
"host": "P1-FT",
"n": 171,
"mn": [
-4530.0,
-4552.3,
12301.0
],
"mx": [
4470.0,
4552.3,
14299.0
],
"src": "기초 평면 EREC 기호(아래 절반 작도, 위 절반 대칭); a 567 평균 (F2 [추론])",
"design_length": "4763.000",
"zr_samples": {
"12301.0..14299.0": 171
}
},
"B11": {
"dia": "H19",
"shape": "U",
"host": "P1-FT",
"n": 19,
"mn": [
-4700.0,
-4537.5,
12725.0
],
"mx": [
4700.0,
4537.5,
13825.0
],
"src": "측면 중간 점 EL 12.825 (F4 [추론])",
"design_length": "10160.000",
"zr_samples": {
"12725.0..12825.0": 10,
"13725.0..13825.0": 9
}
},
"B12": {
"dia": "H19",
"shape": "U",
"host": "P1-FT",
"n": 19,
"mn": [
-4500.0,
-4700.0,
12744.0
],
"mx": [
4500.0,
4700.0,
13844.0
],
"src": "정면 중간 점 EL 12.825 (+19, F4 [추론])",
"design_length": "10160.000",
"zr_samples": {
"12744.0..12844.0": 10,
"13744.0..13844.0": 9
}
},
"B5": {
"dia": "H29",
"shape": "U",
"host": "P1-FT",
"n": 38,
"mn": [
-4700.0,
-4700.0,
13277.5
],
"mx": [
4700.0,
4700.0,
14252.5
],
"src": "측면 상면 점 EL 14.2525, 정면 다리 975; B5/B7 교번, 겹이음 j 미모델 (F3 [추론])",
"design_length": "12880.000",
"zr_samples": {
"13277.5..14252.5": 38
}
},
"B7": {
"dia": "H29",
"shape": "U",
"host": "P1-FT",
"n": 37,
"mn": [
-4700.0,
-4537.5,
13277.5
],
"mx": [
4700.0,
4537.5,
14252.5
],
"src": "측면 상면 점 EL 14.2525, 정면 다리 975; B5/B7 교번, 겹이음 j 미모델 (F3 [추론])",
"design_length": "12880.000",
"zr_samples": {
"13277.5..14252.5": 37
}
},
"B3": {
"dia": "H29",
"shape": "U",
"host": "P1-FT",
"n": 38,
"mn": [
-4600.0,
-4700.0,
13375.0
],
"mx": [
4600.0,
4700.0,
14275.0
],
"src": "정면 상면 점 EL 14.275, 측면 다리 900; B1/B3 교번, 겹이음 j 미모델 (F3 [추론])",
"design_length": "12730.000",
"zr_samples": {
"13375.0..14275.0": 38
}
},
"B6": {
"dia": "H29",
"shape": "U",
"host": "P1-FT",
"n": 38,
"mn": [
-4700.0,
-4700.0,
12347.5
],
"mx": [
4700.0,
4700.0,
14297.5
],
"src": "측면 하면 점 EL 12.3475, 정면 다리 1,950; B6/B8 교번, 겹이음 j 미모델 (F3 [추론])",
"design_length": "14370.000",
"zr_samples": {
"12347.5..14297.5": 38
}
},
"B8": {
"dia": "H29",
"shape": "U",
"host": "P1-FT",
"n": 37,
"mn": [
-4700.0,
-4537.5,
12347.5
],
"mx": [
4700.0,
4537.5,
14297.5
],
"src": "측면 하면 점 EL 12.3475, 정면 다리 1,950; B6/B8 교번, 겹이음 j 미모델 (F3 [추론])",
"design_length": "14370.000",
"zr_samples": {
"12347.5..14297.5": 37
}
},
"B2": {
"dia": "H29",
"shape": "U",
"host": "P1-FT",
"n": 39,
"mn": [
-4700.0,
-4700.0,
12325.0
],
"mx": [
4700.0,
4700.0,
14125.0
],
"src": "정면 하면 점 EL 12.325, 측면 다리 1,800; B2/B4 교번, 겹이음 j 미모델 (F3 [추론])",
"design_length": "14070.000",
"zr_samples": {
"12325.0..14125.0": 39
}
},
"B4": {
"dia": "H29",
"shape": "U",
"host": "P1-FT",
"n": 38,
"mn": [
-4600.0,
-4700.0,
12325.0
],
"mx": [
4600.0,
4700.0,
14125.0
],
"src": "정면 하면 점 EL 12.325, 측면 다리 1,800; B2/B4 교번, 겹이음 j 미모델 (F3 [추론])",
"design_length": "14070.000",
"zr_samples": {
"12325.0..14125.0": 38
}
}
}
},
"done": true
}
@@ -0,0 +1,56 @@
{
"okseong": {
"objects_before": 3862,
"stat": {
"P5_done": 40
},
"sample": {
"P5": {
"a_before": 160.0,
"b_before": 2283.06,
"delta": 57.94,
"a_after": 160.0,
"b_after": 2341.0,
"len_before": 2653.8,
"len_after": 2711.7,
"L_table_minus_bend": null
}
},
"objects_after": 3862,
"saved": true,
"out": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\검토_옥성교P1\\옥성교P1_G5_수정6_20261026.3dm"
},
"rampa": {
"objects_before": 2255,
"stat": {
"P3_done": 108,
"P3-1_done": 48
},
"sample": {
"P3": {
"a_before": 200.0,
"b_before": 1774.06,
"delta": 57.94,
"a_after": 200.0,
"b_after": 1832.0,
"len_before": 2204.8,
"len_after": 2262.7,
"L_table_minus_bend": null
},
"P3-1": {
"a_before": 200.0,
"b_before": 2079.06,
"delta": 57.94,
"a_after": 200.0,
"b_after": 2137.0,
"len_before": 2583.8,
"len_after": 2641.7,
"L_table_minus_bend": null
}
},
"objects_after": 2255,
"saved": true,
"out": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\Ramp-A교P1\\ramp-A G5_수정5_20261026.3dm"
},
"done": true
}
+50
View File
@@ -0,0 +1,50 @@
{
"okseong": {
"objects_before": 3862,
"stat": {
"P5_done": 40
},
"sample": {
"P5": {
"old_len": 2581.4,
"new_len": 2653.8,
"arc_R": 60.0,
"arc_deg": 134.65,
"arc_len": 141.0,
"tail": 80.0
}
},
"objects_after": 3862,
"saved": true,
"out": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\검토_옥성교P1\\옥성교P1_G5_수정5_20261026.3dm"
},
"rampa": {
"objects_before": 2255,
"stat": {
"P3-1_done": 48,
"P3_done": 108
},
"sample": {
"P3-1": {
"old_len": 2417.4,
"new_len": 2583.8,
"arc_R": 135.0,
"arc_deg": 70.03,
"arc_len": 165.0,
"tail": 150.0
},
"P3": {
"old_len": 2112.4,
"new_len": 2204.8,
"arc_R": 60.0,
"arc_deg": 134.65,
"arc_len": 141.0,
"tail": 100.0
}
},
"objects_after": 2255,
"saved": true,
"out": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\Ramp-A교P1\\ramp-A G5_수정3_20261026.3dm"
},
"done": true
}
@@ -0,0 +1,227 @@
{
"P1-RC-P3-1-L01X": {
"bar_world_u_direction": [
1.0,
0.0,
0.0
],
"dims": {
"a(다리: 끝~꼭짓점)": 200.0,
"b(꼭짓점~갈고리호 시작)": 2137.0,
"r(갈고리호 반지름, 중심선)": 135.0,
"호 각도(deg)": 70.03,
"c(갈고리호 길이)": 165.0,
"d(곧은 구간)": 150.0,
"모서리호 반지름": 24.0,
"모서리호 각도": 90.0,
"중심선 전체 길이": 2641.7
},
"d_direction(곧은구간 방향 단위벡터 u,v)": [
0.3416,
-0.9399
],
"points": {
"①_다리_끝(leg end)": {
"world": [
-1068.5,
0.0,
32992.0
],
"2D(u,v)": [
0.0,
-200.0
]
},
"②_꼭짓점(leg line x horizontal line)": {
"world": [
-1068.5,
0.0,
33192.0
],
"2D(u,v)": [
0.0,
0.0
]
},
"③_모서리호_시작": {
"world": [
-1068.5,
0.0,
33168.0
],
"2D(u,v)": [
0.0,
-24.0
]
},
"④_모서리호_끝=수평선_시작": {
"world": [
-1044.5,
0.0,
33192.0
],
"2D(u,v)": [
24.0,
0.0
]
},
"⑤_갈고리호_시작(수평선_끝)": {
"world": [
1068.5,
0.0,
33192.0
],
"2D(u,v)": [
2137.0,
0.0
]
},
"⑥_갈고리호_중심": {
"world": [
1068.5,
0.0,
33057.0
],
"2D(u,v)": [
2137.0,
-135.0
]
},
"⑦_갈고리호_끝=곧은구간_시작": {
"world": [
1195.38,
0.0,
33103.11
],
"2D(u,v)": [
2263.88,
-88.89
]
},
"⑧_곧은구간_끝": {
"world": [
1246.61,
0.0,
32962.13
],
"2D(u,v)": [
2315.11,
-229.87
]
}
}
},
"P1-RC-P3-L01X": {
"bar_world_u_direction": [
1.0,
0.0,
0.0
],
"dims": {
"a(다리: 끝~꼭짓점)": 200.0,
"b(꼭짓점~갈고리호 시작)": 1832.0,
"r(갈고리호 반지름, 중심선)": 60.0,
"호 각도(deg)": 134.65,
"c(갈고리호 길이)": 141.0,
"d(곧은 구간)": 100.0,
"모서리호 반지름": 24.0,
"모서리호 각도": 90.0,
"중심선 전체 길이": 2262.7
},
"d_direction(곧은구간 방향 단위벡터 u,v)": [
-0.7027,
-0.7115
],
"points": {
"①_다리_끝(leg end)": {
"world": [
-916.0,
0.0,
43492.0
],
"2D(u,v)": [
0.0,
-200.0
]
},
"②_꼭짓점(leg line x horizontal line)": {
"world": [
-916.0,
0.0,
43692.0
],
"2D(u,v)": [
0.0,
0.0
]
},
"③_모서리호_시작": {
"world": [
-916.0,
0.0,
43668.0
],
"2D(u,v)": [
0.0,
-24.0
]
},
"④_모서리호_끝=수평선_시작": {
"world": [
-892.0,
0.0,
43692.0
],
"2D(u,v)": [
24.0,
0.0
]
},
"⑤_갈고리호_시작(수평선_끝)": {
"world": [
916.0,
0.0,
43692.0
],
"2D(u,v)": [
1832.0,
0.0
]
},
"⑥_갈고리호_중심": {
"world": [
916.0,
0.0,
43632.0
],
"2D(u,v)": [
1832.0,
-60.0
]
},
"⑦_갈고리호_끝=곧은구간_시작": {
"world": [
958.69,
0.0,
43589.84
],
"2D(u,v)": [
1874.69,
-102.16
]
},
"⑧_곧은구간_끝": {
"world": [
888.42,
0.0,
43518.69
],
"2D(u,v)": [
1804.42,
-173.31
]
}
}
},
"done": true
}
@@ -0,0 +1,227 @@
{
"P1-RC-P3-1-L01X": {
"bar_world_u_direction": [
1.0,
0.0,
0.0
],
"dims": {
"a(다리: 끝~꼭짓점)": 200.0,
"b(꼭짓점~갈고리호 시작)": 2137.0,
"r(갈고리호 반지름, 중심선)": 70.21,
"호 각도(deg)": 134.65,
"c(갈고리호 길이)": 165.0,
"d(곧은 구간)": 150.0,
"모서리호 반지름": 24.0,
"모서리호 각도": 90.0,
"중심선 전체 길이": 2641.7
},
"d_direction(곧은구간 방향 단위벡터 u,v)": [
-0.7027,
-0.7115
],
"points": {
"①_다리_끝(leg end)": {
"world": [
-1068.5,
0.0,
32992.0
],
"2D(u,v)": [
0.0,
-200.0
]
},
"②_꼭짓점(leg line x horizontal line)": {
"world": [
-1068.5,
0.0,
33192.0
],
"2D(u,v)": [
0.0,
0.0
]
},
"③_모서리호_시작": {
"world": [
-1068.5,
0.0,
33168.0
],
"2D(u,v)": [
0.0,
-24.0
]
},
"④_모서리호_끝=수평선_시작": {
"world": [
-1044.5,
0.0,
33192.0
],
"2D(u,v)": [
24.0,
0.0
]
},
"⑤_갈고리호_시작(수평선_끝)": {
"world": [
1068.5,
0.0,
33192.0
],
"2D(u,v)": [
2137.0,
0.0
]
},
"⑥_갈고리호_중심": {
"world": [
1068.5,
0.0,
33121.79
],
"2D(u,v)": [
2137.0,
-70.21
]
},
"⑦_갈고리호_끝=곧은구간_시작": {
"world": [
1118.45,
0.0,
33072.45
],
"2D(u,v)": [
2186.95,
-119.55
]
},
"⑧_곧은구간_끝": {
"world": [
1013.05,
0.0,
32965.73
],
"2D(u,v)": [
2081.55,
-226.27
]
}
}
},
"P1-RC-P3-L01X": {
"bar_world_u_direction": [
1.0,
0.0,
0.0
],
"dims": {
"a(다리: 끝~꼭짓점)": 200.0,
"b(꼭짓점~갈고리호 시작)": 1832.0,
"r(갈고리호 반지름, 중심선)": 60.0,
"호 각도(deg)": 134.65,
"c(갈고리호 길이)": 141.0,
"d(곧은 구간)": 100.0,
"모서리호 반지름": 24.0,
"모서리호 각도": 90.0,
"중심선 전체 길이": 2262.7
},
"d_direction(곧은구간 방향 단위벡터 u,v)": [
-0.7027,
-0.7115
],
"points": {
"①_다리_끝(leg end)": {
"world": [
-916.0,
0.0,
43492.0
],
"2D(u,v)": [
0.0,
-200.0
]
},
"②_꼭짓점(leg line x horizontal line)": {
"world": [
-916.0,
0.0,
43692.0
],
"2D(u,v)": [
0.0,
0.0
]
},
"③_모서리호_시작": {
"world": [
-916.0,
0.0,
43668.0
],
"2D(u,v)": [
0.0,
-24.0
]
},
"④_모서리호_끝=수평선_시작": {
"world": [
-892.0,
0.0,
43692.0
],
"2D(u,v)": [
24.0,
0.0
]
},
"⑤_갈고리호_시작(수평선_끝)": {
"world": [
916.0,
0.0,
43692.0
],
"2D(u,v)": [
1832.0,
0.0
]
},
"⑥_갈고리호_중심": {
"world": [
916.0,
0.0,
43632.0
],
"2D(u,v)": [
1832.0,
-60.0
]
},
"⑦_갈고리호_끝=곧은구간_시작": {
"world": [
958.69,
0.0,
43589.84
],
"2D(u,v)": [
1874.69,
-102.16
]
},
"⑧_곧은구간_끝": {
"world": [
888.42,
0.0,
43518.69
],
"2D(u,v)": [
1804.42,
-173.31
]
}
}
},
"done": true
}
+61
View File
@@ -0,0 +1,61 @@
{
"okseong": {
"P5": {
"n": 40,
"leg_end_below_bend": 40,
"hook_tail_points_down": 40,
"tail_dz_range": [
-56.9,
-56.9
],
"outside_points_by_part": {
"leg end": 25,
"middle": 108,
"hook end": 21
},
"outside_z_range": [
18175,
18175
]
}
},
"rampa": {
"P3-1": {
"n": 48,
"leg_end_below_bend": 48,
"hook_tail_points_down": 48,
"tail_dz_range": [
-141.0,
-141.0
],
"outside_points_by_part": {
"leg end": 1728,
"middle": 5088,
"hook end": 1680
},
"outside_z_range": [
32962,
45208
]
},
"P3": {
"n": 108,
"leg_end_below_bend": 108,
"hook_tail_points_down": 108,
"tail_dz_range": [
-71.1,
-71.1
],
"outside_points_by_part": {
"leg end": 393,
"hook end": 382,
"middle": 1080
},
"outside_z_range": [
43492,
45451
]
}
},
"done": true
}
+186
View File
@@ -0,0 +1,186 @@
{
"ungok": {
"per_dia": {
"16": {
"req_center_R": 23.9,
"bars": 585,
"arcs": 1170,
"min_R_found": 24.0,
"arcs_below": 0
},
"19": {
"req_center_R": 42.93,
"bars": 373,
"arcs": 823,
"min_R_found": 42.75,
"arcs_below": 144
},
"25": {
"req_center_R": 56.95,
"bars": 244,
"arcs": 824,
"min_R_found": 56.95,
"arcs_below": 0
},
"29": {
"req_center_R": 64.56,
"bars": 160,
"arcs": 320,
"min_R_found": 65.25,
"arcs_below": 0
},
"32": {
"req_center_R": 71.66,
"bars": 46,
"arcs": 46,
"min_R_found": 340.0,
"arcs_below": 0
}
},
"below_by_mark": {
"P3/H19": {
"bars": 72,
"arcs": 144,
"min_R": 42.75
}
}
},
"sanoe": {
"per_dia": {
"13": {
"req_center_R": 19.2,
"bars": 186,
"arcs": 372,
"min_R_found": 19.5,
"arcs_below": 0
},
"16": {
"req_center_R": 23.9,
"bars": 181,
"arcs": 516,
"min_R_found": 24.0,
"arcs_below": 0
},
"19": {
"req_center_R": 42.93,
"bars": 64,
"arcs": 128,
"min_R_found": 42.93,
"arcs_below": 0
},
"22": {
"req_center_R": 49.85,
"bars": 263,
"arcs": 902,
"min_R_found": 49.85,
"arcs_below": 0
},
"32": {
"req_center_R": 71.66,
"bars": 131,
"arcs": 220,
"min_R_found": 72.0,
"arcs_below": 0
}
},
"below_by_mark": {}
},
"okseong": {
"per_dia": {
"16": {
"req_center_R": 23.9,
"bars": 168,
"arcs": 336,
"min_R_found": 24.0,
"arcs_below": 0
},
"19": {
"req_center_R": 42.93,
"bars": 463,
"arcs": 1203,
"min_R_found": 42.93,
"arcs_below": 0
},
"22": {
"req_center_R": 49.85,
"bars": 12,
"arcs": 48,
"min_R_found": 49.85,
"arcs_below": 0
},
"25": {
"req_center_R": 56.95,
"bars": 438,
"arcs": 1598,
"min_R_found": 56.25,
"arcs_below": 90
},
"29": {
"req_center_R": 64.56,
"bars": 304,
"arcs": 608,
"min_R_found": 65.25,
"arcs_below": 0
},
"32": {
"req_center_R": 71.66,
"bars": 88,
"arcs": 198,
"min_R_found": 72.0,
"arcs_below": 0
}
},
"below_by_mark": {
"C13/H25": {
"bars": 8,
"arcs": 40,
"min_R": 56.25
},
"C9/H25": {
"bars": 10,
"arcs": 50,
"min_R": 56.25
}
}
},
"rampa": {
"per_dia": {
"16": {
"req_center_R": 23.9,
"bars": 542,
"arcs": 1454,
"min_R_found": 24.0,
"arcs_below": 0
},
"19": {
"req_center_R": 42.93,
"bars": 263,
"arcs": 1022,
"min_R_found": 42.75,
"arcs_below": 60
},
"25": {
"req_center_R": 56.95,
"bars": 9,
"arcs": 18,
"min_R_found": 56.95,
"arcs_below": 0
},
"29": {
"req_center_R": 64.56,
"bars": 34,
"arcs": 68,
"min_R_found": 65.25,
"arcs_below": 0
}
},
"below_by_mark": {
"C12/H19": {
"bars": 12,
"arcs": 60,
"min_R": 42.75
}
}
},
"done": true
}
@@ -0,0 +1,107 @@
{
"objects_before": 3862,
"stat": {
"B6_done": 38,
"B8_done": 37,
"B5_done": 38,
"B7_done": 37,
"B12_done": 19,
"B11_done": 19,
"C1_done": 13,
"C3_done": 13,
"C6_done": 12,
"C2_done": 13,
"C5_done": 12,
"C4_done": 12,
"B1_done": 39,
"B3_done": 38,
"B2_done": 39,
"B4_done": 38
},
"info": {
"B6": {
"bars": 38,
"avg_len_old": 13186.0,
"avg_len_new_sum_of_pieces": 14256.0
},
"B8": {
"bars": 37,
"avg_len_old": 13186.0,
"avg_len_new_sum_of_pieces": 14256.0
},
"B5": {
"bars": 38,
"avg_len_old": 11294.0,
"avg_len_new_sum_of_pieces": 12824.0
},
"B7": {
"bars": 37,
"avg_len_old": 11294.0,
"avg_len_new_sum_of_pieces": 12824.0
},
"B12": {
"bars": 19,
"avg_len_old": 9563.1,
"avg_len_new_sum_of_pieces": 10123.1
},
"B11": {
"bars": 19,
"avg_len_old": 9563.1,
"avg_len_new_sum_of_pieces": 10123.1
},
"C1": {
"bars": 13,
"avg_len_old": 14182.2,
"avg_len_new_sum_of_pieces": 15692.2
},
"C3": {
"bars": 13,
"avg_len_old": 11888.2,
"avg_len_new_sum_of_pieces": 13398.2
},
"C6": {
"bars": 12,
"avg_len_old": 11888.2,
"avg_len_new_sum_of_pieces": 13398.2
},
"C2": {
"bars": 13,
"avg_len_old": 11888.2,
"avg_len_new_sum_of_pieces": 13398.2
},
"C5": {
"bars": 12,
"avg_len_old": 11888.2,
"avg_len_new_sum_of_pieces": 13398.2
},
"C4": {
"bars": 12,
"avg_len_old": 14182.2,
"avg_len_new_sum_of_pieces": 15692.2
},
"B1": {
"bars": 39,
"avg_len_old": 11144.0,
"avg_len_new_sum_of_pieces": 12674.0
},
"B3": {
"bars": 38,
"avg_len_old": 11144.0,
"avg_len_new_sum_of_pieces": 12674.0
},
"B2": {
"bars": 39,
"avg_len_old": 12944.0,
"avg_len_new_sum_of_pieces": 14014.0
},
"B4": {
"bars": 38,
"avg_len_old": 12944.0,
"avg_len_new_sum_of_pieces": 14014.0
}
},
"objects_after": 4696,
"saved": true,
"out": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\검토_옥성교P1\\옥성교P1_G5_수정7_20261027.3dm",
"done": true
}
@@ -0,0 +1,47 @@
{
"objects_before": 2004,
"stat": {
"C7_done": 51,
"C8_done": 21,
"C9_done": 51,
"C10_done": 7,
"C12_done": 6,
"C13_done": 20
},
"info": {
"C7": {
"bars": 51,
"avg_len_old": 7649.3,
"avg_len_new_sum_of_pieces": 8969.3
},
"C8": {
"bars": 21,
"avg_len_old": 9134.4,
"avg_len_new_sum_of_pieces": 10454.4
},
"C9": {
"bars": 51,
"avg_len_old": 7390.6,
"avg_len_new_sum_of_pieces": 8710.6
},
"C10": {
"bars": 7,
"avg_len_old": 17796.8,
"avg_len_new_sum_of_pieces": 19116.8
},
"C12": {
"bars": 6,
"avg_len_old": 24338.4,
"avg_len_new_sum_of_pieces": 25658.4
},
"C13": {
"bars": 20,
"avg_len_old": 10153.1,
"avg_len_new_sum_of_pieces": 10813.1
}
},
"objects_after": 2316,
"saved": true,
"out": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\검토_산외교P1\\산외교P1 G5_수정4_20261026.3dm",
"done": true
}
@@ -0,0 +1,29 @@
{
"objects_before": 2316,
"stat": {
"B2_done": 31,
"B5_done": 31,
"B8_done": 7
},
"info": {
"B2": {
"bars": 31,
"avg_len_old": 11757.2,
"avg_len_new_sum_of_pieces": 12757.2
},
"B5": {
"bars": 31,
"avg_len_old": 11713.2,
"avg_len_new_sum_of_pieces": 12713.2
},
"B8": {
"bars": 7,
"avg_len_old": 29338.8,
"avg_len_new_sum_of_pieces": 30478.8
}
},
"objects_after": 2454,
"saved": true,
"out": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\검토_산외교P1\\산외교P1 G5_수정5_20261027.3dm",
"done": true
}
@@ -0,0 +1,35 @@
{
"운곡교p1_수정2_20261023.3dm": {
"layers_turned_on": 38,
"still_off_that_reviewed_shows": [],
"layers_off_now": 0,
"objects": 3236,
"written": true,
"saved": true
},
"산외교P1 G5_수정_20261023.3dm": {
"layers_turned_on": 0,
"still_off_that_reviewed_shows": [],
"layers_off_now": 0,
"objects": 2004,
"written": true,
"saved": true
},
"옥성교P1_G5_수정_20261023.3dm": {
"layers_turned_on": 0,
"still_off_that_reviewed_shows": [],
"layers_off_now": 0,
"objects": 3862,
"written": true,
"saved": true
},
"ramp-A G5_수정_20261023.3dm": {
"layers_turned_on": 0,
"still_off_that_reviewed_shows": [],
"layers_off_now": 0,
"objects": 2255,
"written": true,
"saved": true
},
"done": true
}
@@ -0,0 +1,458 @@
{
"n": 171,
"planes": {
"YZ(x=const)": 171
},
"footing_half": [
4800.0,
4800.0
],
"lines": [
{
"plane": "YZ(x=const)",
"const": -4530.0,
"n": 10,
"first": [
[
-4552.3,
-3985.3,
"tails toward -Y"
],
[
-3533.5,
-2966.5,
"tails toward -Y"
],
[
-2533.5,
-1966.5,
"tails toward -Y"
]
],
"overlapping_neighbours": 1
},
{
"plane": "YZ(x=const)",
"const": -4030.0,
"n": 8,
"first": [
[
-4033.5,
-3466.5,
"tails toward -Y"
],
[
-3033.5,
-2466.5,
"tails toward -Y"
],
[
-2033.5,
-1466.5,
"tails toward -Y"
]
],
"overlapping_neighbours": 0
},
{
"plane": "YZ(x=const)",
"const": -3530.0,
"n": 10,
"first": [
[
-4552.3,
-3985.3,
"tails toward -Y"
],
[
-3533.5,
-2966.5,
"tails toward -Y"
],
[
-2533.5,
-1966.5,
"tails toward -Y"
]
],
"overlapping_neighbours": 1
},
{
"plane": "YZ(x=const)",
"const": -3030.0,
"n": 8,
"first": [
[
-4033.5,
-3466.5,
"tails toward -Y"
],
[
-3033.5,
-2466.5,
"tails toward -Y"
],
[
-2033.5,
-1466.5,
"tails toward -Y"
]
],
"overlapping_neighbours": 0
},
{
"plane": "YZ(x=const)",
"const": -2530.0,
"n": 10,
"first": [
[
-4552.3,
-3985.3,
"tails toward -Y"
],
[
-3533.5,
-2966.5,
"tails toward -Y"
],
[
-2533.5,
-1966.5,
"tails toward -Y"
]
],
"overlapping_neighbours": 1
},
{
"plane": "YZ(x=const)",
"const": -2030.0,
"n": 8,
"first": [
[
-4033.5,
-3466.5,
"tails toward -Y"
],
[
-3033.5,
-2466.5,
"tails toward -Y"
],
[
-2033.5,
-1466.5,
"tails toward -Y"
]
],
"overlapping_neighbours": 0
},
{
"plane": "YZ(x=const)",
"const": -1530.0,
"n": 10,
"first": [
[
-4552.3,
-3985.3,
"tails toward -Y"
],
[
-3533.5,
-2966.5,
"tails toward -Y"
],
[
-2533.5,
-1966.5,
"tails toward -Y"
]
],
"overlapping_neighbours": 1
},
{
"plane": "YZ(x=const)",
"const": -1030.0,
"n": 8,
"first": [
[
-4033.5,
-3466.5,
"tails toward -Y"
],
[
-3033.5,
-2466.5,
"tails toward -Y"
],
[
-2033.5,
-1466.5,
"tails toward -Y"
]
],
"overlapping_neighbours": 0
},
{
"plane": "YZ(x=const)",
"const": -530.0,
"n": 10,
"first": [
[
-4552.3,
-3985.3,
"tails toward -Y"
],
[
-3533.5,
-2966.5,
"tails toward -Y"
],
[
-2533.5,
-1966.5,
"tails toward -Y"
]
],
"overlapping_neighbours": 1
},
{
"plane": "YZ(x=const)",
"const": -30.0,
"n": 8,
"first": [
[
-4033.5,
-3466.5,
"tails toward -Y"
],
[
-3033.5,
-2466.5,
"tails toward -Y"
],
[
-2033.5,
-1466.5,
"tails toward -Y"
]
],
"overlapping_neighbours": 0
},
{
"plane": "YZ(x=const)",
"const": 470.0,
"n": 9,
"first": [
[
-4552.3,
-3985.3,
"tails toward -Y"
],
[
-3533.5,
-2966.5,
"tails toward -Y"
],
[
-2533.5,
-1966.5,
"tails toward -Y"
]
],
"overlapping_neighbours": 0
},
{
"plane": "YZ(x=const)",
"const": 970.0,
"n": 8,
"first": [
[
-4033.5,
-3466.5,
"tails toward -Y"
],
[
-3033.5,
-2466.5,
"tails toward -Y"
],
[
-2033.5,
-1466.5,
"tails toward -Y"
]
],
"overlapping_neighbours": 0
},
{
"plane": "YZ(x=const)",
"const": 1470.0,
"n": 10,
"first": [
[
-4552.3,
-3985.3,
"tails toward -Y"
],
[
-3533.5,
-2966.5,
"tails toward -Y"
],
[
-2533.5,
-1966.5,
"tails toward -Y"
]
],
"overlapping_neighbours": 1
},
{
"plane": "YZ(x=const)",
"const": 1970.0,
"n": 8,
"first": [
[
-4033.5,
-3466.5,
"tails toward -Y"
],
[
-3033.5,
-2466.5,
"tails toward -Y"
],
[
-2033.5,
-1466.5,
"tails toward -Y"
]
],
"overlapping_neighbours": 0
},
{
"plane": "YZ(x=const)",
"const": 2470.0,
"n": 10,
"first": [
[
-4552.3,
-3985.3,
"tails toward -Y"
],
[
-3533.5,
-2966.5,
"tails toward -Y"
],
[
-2533.5,
-1966.5,
"tails toward -Y"
]
],
"overlapping_neighbours": 1
},
{
"plane": "YZ(x=const)",
"const": 2970.0,
"n": 8,
"first": [
[
-4033.5,
-3466.5,
"tails toward -Y"
],
[
-3033.5,
-2466.5,
"tails toward -Y"
],
[
-2033.5,
-1466.5,
"tails toward -Y"
]
],
"overlapping_neighbours": 0
},
{
"plane": "YZ(x=const)",
"const": 3470.0,
"n": 10,
"first": [
[
-4552.3,
-3985.3,
"tails toward -Y"
],
[
-3533.5,
-2966.5,
"tails toward -Y"
],
[
-2533.5,
-1966.5,
"tails toward -Y"
]
],
"overlapping_neighbours": 1
},
{
"plane": "YZ(x=const)",
"const": 3970.0,
"n": 8,
"first": [
[
-4033.5,
-3466.5,
"tails toward -Y"
],
[
-3033.5,
-2466.5,
"tails toward -Y"
],
[
-2033.5,
-1466.5,
"tails toward -Y"
]
],
"overlapping_neighbours": 0
},
{
"plane": "YZ(x=const)",
"const": 4470.0,
"n": 10,
"first": [
[
-4552.3,
-3985.3,
"tails toward -Y"
],
[
-3533.5,
-2966.5,
"tails toward -Y"
],
[
-2533.5,
-1966.5,
"tails toward -Y"
]
],
"overlapping_neighbours": 1
}
],
"n_lines": 19,
"tail_dirs": {
"tails toward -Y": 171
},
"z": [
126.0,
2124.0
],
"done": true
}
@@ -0,0 +1,19 @@
{
"objects_before": 2255,
"stat": {
"done": 48
},
"sample": {
"name": "P1-RC-P3-1-L24Y",
"r": 70.213,
"angle": 134.645,
"arc_len": 165.0,
"tail": 150.0,
"len_before": 2641.7,
"len_after": 2641.7
},
"objects_after": 2255,
"saved": true,
"out": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\Ramp-A교P1\\ramp-A G5_수정6_20261026.3dm",
"done": true
}
+287
View File
@@ -0,0 +1,287 @@
{
"P3-2": {
"n": 30,
"name": "P1-RC-P3-2-30",
"dia": "H16",
"shape": "U",
"design_length": "3342.000",
"src": "plane 172.6225 deg through the centre (S3 [추론]); bottom EL 32.852; c 200 welded to P1-2",
"len": 3276.3,
"segs": [
[
"PolylineCurve",
184.1,
null,
null,
[
1016.5,
-131.6,
33617.1
],
[
1016.5,
-131.6,
33433.0
],
[
-0.0,
0.0,
-1.0
]
],
[
"ArcCurve",
31.66,
135.0,
13.44,
[
1016.5,
-131.6,
33433.0
],
[
1012.9,
-131.1,
33401.6
],
[
0.0,
0.0,
-1.0
]
],
[
"PolylineCurve",
458.55,
null,
null,
[
1012.9,
-131.1,
33401.6
],
[
907.2,
-117.5,
32955.6
],
[
-0.23,
0.03,
-0.973
]
],
[
"ArcCurve",
180.4,
135.0,
76.56,
[
907.2,
-117.5,
32955.6
],
[
777.0,
-100.6,
32852.0
],
[
-0.23,
0.03,
-0.973
]
],
[
"PolylineCurve",
1566.9,
null,
null,
[
777.0,
-100.6,
32852.0
],
[
-777.0,
100.6,
32852.0
],
[
-0.992,
0.128,
0.0
]
],
[
"ArcCurve",
180.4,
135.0,
76.56,
[
-777.0,
100.6,
32852.0
],
[
-907.2,
117.5,
32955.6
],
[
-0.992,
0.128,
-0.0
]
],
[
"PolylineCurve",
458.55,
null,
null,
[
-907.2,
117.5,
32955.6
],
[
-1012.9,
131.1,
33401.6
],
[
-0.23,
0.03,
0.973
]
],
[
"ArcCurve",
31.66,
135.0,
13.44,
[
-1012.9,
131.1,
33401.6
],
[
-1016.5,
131.6,
33433.0
],
[
-0.23,
0.03,
0.973
]
],
[
"PolylineCurve",
184.1,
null,
null,
[
-1016.5,
131.6,
33433.0
],
[
-1016.5,
131.6,
33617.1
],
[
-0.0,
0.0,
1.0
]
]
],
"bbox": [
-1016.5,
-131.6,
32852.0,
1016.5,
131.6,
33617.1
],
"sample_positions(centre x,y,zmin,zmax)": [
[
0,
0,
32852,
33617
]
]
},
"P1-2": {
"n": 61,
"name": "P1-RC-P1-2-61",
"dia": "H22",
"shape": "I",
"design_length": "3400.000",
"src": "angle 355.5734 deg; D4 단면 G-G·J-J 61개; r 999.5 (S2); EL 33.192~36.592; 커플러 이음 (S6)",
"len": 3400.0,
"segs": [],
"bbox": [
996.5,
-77.1,
33192.0,
996.5,
-77.1,
36592.0
],
"sample_positions(centre x,y,zmin,zmax)": [
[
997,
-77,
33192,
36592
],
[
983,
-179,
33192,
36592
],
[
960,
-279,
33192,
36592
],
[
926,
-377,
33192,
36592
],
[
882,
-470,
33192,
36592
],
[
829,
-558,
33192,
36592
],
[
767,
-640,
33192,
36592
],
[
698,
-716,
33192,
36592
]
]
},
"done": true
}
+42
View File
@@ -0,0 +1,42 @@
{
"objects_before": 2255,
"stat": {
"done": 30
},
"samples": [
{
"name": "P1-RC-P3-2-30",
"old_len": 3276.3,
"new_len": 3321.4,
"W": 2050.0,
"h": 646.0,
"z": [
32852.0,
33498.0
],
"old_z": [
32852.0,
33617.1
]
},
{
"name": "P1-RC-P3-2-29",
"old_len": 3276.3,
"new_len": 3321.4,
"W": 2050.0,
"h": 646.0,
"z": [
32852.0,
33498.0
],
"old_z": [
32852.0,
33617.1
]
}
],
"objects_after": 2255,
"saved": true,
"out": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\Ramp-A교P1\\ramp-A G5_수정4_20261026.3dm",
"done": true
}
+351
View File
@@ -0,0 +1,351 @@
{
"P3": {
"n": 108,
"name": "P1-RC-P3-L01X",
"dia": "H16",
"shape": "tie-90/135",
"design_length": "2273.000",
"src": "EL 43.692; X 방향; 90° 다리·135° 갈고리 기본 (K4 [추론])",
"len": 2204.8,
"segs": [
[
"PolylineCurve",
176.0,
null,
null,
[
-916.0,
0.0,
43492.0
],
[
-916.0,
0.0,
43668.0
],
[
-0.0,
0.0,
1.0
]
],
[
"ArcCurve",
37.7,
24.0,
90.0,
[
-916.0,
0.0,
43668.0
],
[
-892.0,
0.0,
43692.0
],
[
0.0,
-0.0,
1.0
]
],
[
"PolylineCurve",
1750.06,
null,
null,
[
-892.0,
0.0,
43692.0
],
[
858.1,
0.0,
43692.0
],
[
1.0,
0.0,
0.0
]
],
[
"ArcCurve",
141.0,
60.0,
134.65,
[
858.1,
0.0,
43692.0
],
[
900.7,
0.0,
43589.8
],
[
1.0,
0.0,
0.0
]
],
[
"LineCurve",
100.0,
null,
null,
[
900.7,
0.0,
43589.8
],
[
830.5,
0.0,
43518.7
],
[
-0.703,
0.0,
-0.711
]
]
],
"bbox": [
-916.0,
0.0,
43492.0,
918.1,
0.0,
43692.0
],
"sample_positions(centre x,y,zmin,zmax)": [
[
1,
0,
43492,
43692
],
[
0,
1,
43508,
43708
],
[
-1,
0,
43792,
43992
],
[
0,
-1,
43808,
44008
],
[
1,
0,
44092,
44292
],
[
0,
1,
44108,
44308
],
[
-1,
0,
44392,
44592
],
[
0,
-1,
44408,
44608
]
]
},
"P3-1": {
"n": 48,
"name": "P1-RC-P3-1-L01X",
"dia": "H16",
"shape": "tie-90/135",
"design_length": "2652.000",
"src": "EL 33.192; X 방향 (S5 [추론])",
"len": 2583.8,
"segs": [
[
"PolylineCurve",
176.0,
null,
null,
[
-1068.5,
0.0,
32992.0
],
[
-1068.5,
0.0,
33168.0
],
[
0.0,
0.0,
1.0
]
],
[
"ArcCurve",
37.7,
24.0,
90.0,
[
-1068.5,
0.0,
33168.0
],
[
-1044.5,
0.0,
33192.0
],
[
0.0,
-0.0,
1.0
]
],
[
"PolylineCurve",
2055.06,
null,
null,
[
-1044.5,
0.0,
33192.0
],
[
1010.6,
0.0,
33192.0
],
[
1.0,
0.0,
0.0
]
],
[
"ArcCurve",
165.0,
135.0,
70.03,
[
1010.6,
0.0,
33192.0
],
[
1137.4,
0.0,
33103.1
],
[
1.0,
0.0,
0.0
]
],
[
"LineCurve",
150.0,
null,
null,
[
1137.4,
0.0,
33103.1
],
[
1188.7,
0.0,
32962.1
],
[
0.342,
0.0,
-0.94
]
]
],
"bbox": [
-1068.5,
0.0,
32962.1,
1188.7,
0.0,
33192.0
],
"sample_positions(centre x,y,zmin,zmax)": [
[
60,
0,
32962,
33192
],
[
0,
60,
32978,
33208
],
[
-60,
0,
33562,
33792
],
[
0,
-60,
33578,
33808
],
[
60,
0,
34162,
34392
],
[
0,
60,
34178,
34408
],
[
-60,
0,
34762,
34992
],
[
0,
-60,
34778,
35008
]
]
},
"done": true
}
+708
View File
@@ -0,0 +1,708 @@
{
"okseong_C13": {
"name": "P1-RC-C13-x+3475L",
"length": 6148.4,
"planar": false,
"variants": {
"blend=False cap=Flat fit=True atol=0.001 ang=1.0": {
"n": 0,
"solid": false
},
"blend=False cap=Flat fit=True atol=0.001 ang=5.0": {
"n": 0,
"solid": false
},
"blend=False cap=Flat fit=True atol=0.01 ang=1.0": {
"n": 0,
"solid": false
},
"blend=False cap=Flat fit=True atol=0.01 ang=5.0": {
"n": 0,
"solid": false
},
"blend=False cap=Flat fit=True atol=0.1 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Flat fit=True atol=0.1 ang=5.0": {
"n": 1,
"solid": true
},
"blend=False cap=Flat fit=False atol=0.001 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Flat fit=False atol=0.001 ang=5.0": {
"n": 1,
"solid": true
},
"blend=False cap=Flat fit=False atol=0.01 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Flat fit=False atol=0.01 ang=5.0": {
"n": 1,
"solid": true
},
"blend=False cap=Flat fit=False atol=0.1 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Flat fit=False atol=0.1 ang=5.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=True atol=0.001 ang=1.0": {
"n": 0,
"solid": false
},
"blend=False cap=Round fit=True atol=0.001 ang=5.0": {
"n": 0,
"solid": false
},
"blend=False cap=Round fit=True atol=0.01 ang=1.0": {
"n": 0,
"solid": false
},
"blend=False cap=Round fit=True atol=0.01 ang=5.0": {
"n": 0,
"solid": false
},
"blend=False cap=Round fit=True atol=0.1 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=True atol=0.1 ang=5.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=False atol=0.001 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=False atol=0.001 ang=5.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=False atol=0.01 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=False atol=0.01 ang=5.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=False atol=0.1 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=False atol=0.1 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=True atol=0.001 ang=1.0": {
"n": 0,
"solid": false
},
"blend=True cap=Flat fit=True atol=0.001 ang=5.0": {
"n": 0,
"solid": false
},
"blend=True cap=Flat fit=True atol=0.01 ang=1.0": {
"n": 0,
"solid": false
},
"blend=True cap=Flat fit=True atol=0.01 ang=5.0": {
"n": 0,
"solid": false
},
"blend=True cap=Flat fit=True atol=0.1 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=True atol=0.1 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=False atol=0.001 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=False atol=0.001 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=False atol=0.01 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=False atol=0.01 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=False atol=0.1 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=False atol=0.1 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=True atol=0.001 ang=1.0": {
"n": 0,
"solid": false
},
"blend=True cap=Round fit=True atol=0.001 ang=5.0": {
"n": 0,
"solid": false
},
"blend=True cap=Round fit=True atol=0.01 ang=1.0": {
"n": 0,
"solid": false
},
"blend=True cap=Round fit=True atol=0.01 ang=5.0": {
"n": 0,
"solid": false
},
"blend=True cap=Round fit=True atol=0.1 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=True atol=0.1 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=False atol=0.001 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=False atol=0.001 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=False atol=0.01 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=False atol=0.01 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=False atol=0.1 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=False atol=0.1 ang=5.0": {
"n": 1,
"solid": true
}
},
"nurbs_pipe": {
"n": 0,
"solid": false
},
"turn_planes": [
[
0.951,
0.309,
0.0,
90.0
],
[
0.951,
0.309,
0.0,
15.66
],
[
0.951,
0.309,
0.0,
74.34
],
[
0.951,
0.309,
0.0,
90.0
],
[
0.951,
0.309,
-0.0,
90.0
]
]
},
"okseong_C9": {
"name": "P1-RC-C9-x-3225L",
"length": 6330.5,
"planar": false,
"variants": {
"blend=False cap=Flat fit=True atol=0.001 ang=1.0": {
"n": 0,
"solid": false
},
"blend=False cap=Flat fit=True atol=0.001 ang=5.0": {
"n": 0,
"solid": false
},
"blend=False cap=Flat fit=True atol=0.01 ang=1.0": {
"n": 0,
"solid": false
},
"blend=False cap=Flat fit=True atol=0.01 ang=5.0": {
"n": 0,
"solid": false
},
"blend=False cap=Flat fit=True atol=0.1 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Flat fit=True atol=0.1 ang=5.0": {
"n": 1,
"solid": true
},
"blend=False cap=Flat fit=False atol=0.001 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Flat fit=False atol=0.001 ang=5.0": {
"n": 1,
"solid": true
},
"blend=False cap=Flat fit=False atol=0.01 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Flat fit=False atol=0.01 ang=5.0": {
"n": 1,
"solid": true
},
"blend=False cap=Flat fit=False atol=0.1 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Flat fit=False atol=0.1 ang=5.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=True atol=0.001 ang=1.0": {
"n": 0,
"solid": false
},
"blend=False cap=Round fit=True atol=0.001 ang=5.0": {
"n": 0,
"solid": false
},
"blend=False cap=Round fit=True atol=0.01 ang=1.0": {
"n": 0,
"solid": false
},
"blend=False cap=Round fit=True atol=0.01 ang=5.0": {
"n": 0,
"solid": false
},
"blend=False cap=Round fit=True atol=0.1 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=True atol=0.1 ang=5.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=False atol=0.001 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=False atol=0.001 ang=5.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=False atol=0.01 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=False atol=0.01 ang=5.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=False atol=0.1 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=False atol=0.1 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=True atol=0.001 ang=1.0": {
"n": 0,
"solid": false
},
"blend=True cap=Flat fit=True atol=0.001 ang=5.0": {
"n": 0,
"solid": false
},
"blend=True cap=Flat fit=True atol=0.01 ang=1.0": {
"n": 0,
"solid": false
},
"blend=True cap=Flat fit=True atol=0.01 ang=5.0": {
"n": 0,
"solid": false
},
"blend=True cap=Flat fit=True atol=0.1 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=True atol=0.1 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=False atol=0.001 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=False atol=0.001 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=False atol=0.01 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=False atol=0.01 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=False atol=0.1 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=False atol=0.1 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=True atol=0.001 ang=1.0": {
"n": 0,
"solid": false
},
"blend=True cap=Round fit=True atol=0.001 ang=5.0": {
"n": 0,
"solid": false
},
"blend=True cap=Round fit=True atol=0.01 ang=1.0": {
"n": 0,
"solid": false
},
"blend=True cap=Round fit=True atol=0.01 ang=5.0": {
"n": 0,
"solid": false
},
"blend=True cap=Round fit=True atol=0.1 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=True atol=0.1 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=False atol=0.001 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=False atol=0.001 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=False atol=0.01 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=False atol=0.01 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=False atol=0.1 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=False atol=0.1 ang=5.0": {
"n": 1,
"solid": true
}
},
"nurbs_pipe": {
"n": 0,
"solid": false
},
"turn_planes": [
[
0.951,
0.309,
-0.0,
90.0
],
[
0.951,
0.309,
0.0,
15.66
],
[
0.951,
0.309,
0.0,
74.34
],
[
0.951,
0.309,
-0.0,
90.0
],
[
0.951,
0.309,
0.0,
90.0
]
]
},
"rampa_C12": {
"name": "P1-RC-C12-x+2500L",
"length": 4281.4,
"planar": true,
"variants": {
"blend=False cap=Flat fit=True atol=0.001 ang=1.0": {
"n": 0,
"solid": false
},
"blend=False cap=Flat fit=True atol=0.001 ang=5.0": {
"n": 0,
"solid": false
},
"blend=False cap=Flat fit=True atol=0.01 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Flat fit=True atol=0.01 ang=5.0": {
"n": 1,
"solid": true
},
"blend=False cap=Flat fit=True atol=0.1 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Flat fit=True atol=0.1 ang=5.0": {
"n": 1,
"solid": true
},
"blend=False cap=Flat fit=False atol=0.001 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Flat fit=False atol=0.001 ang=5.0": {
"n": 1,
"solid": true
},
"blend=False cap=Flat fit=False atol=0.01 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Flat fit=False atol=0.01 ang=5.0": {
"n": 1,
"solid": true
},
"blend=False cap=Flat fit=False atol=0.1 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Flat fit=False atol=0.1 ang=5.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=True atol=0.001 ang=1.0": {
"n": 0,
"solid": false
},
"blend=False cap=Round fit=True atol=0.001 ang=5.0": {
"n": 0,
"solid": false
},
"blend=False cap=Round fit=True atol=0.01 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=True atol=0.01 ang=5.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=True atol=0.1 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=True atol=0.1 ang=5.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=False atol=0.001 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=False atol=0.001 ang=5.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=False atol=0.01 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=False atol=0.01 ang=5.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=False atol=0.1 ang=1.0": {
"n": 1,
"solid": true
},
"blend=False cap=Round fit=False atol=0.1 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=True atol=0.001 ang=1.0": {
"n": 0,
"solid": false
},
"blend=True cap=Flat fit=True atol=0.001 ang=5.0": {
"n": 0,
"solid": false
},
"blend=True cap=Flat fit=True atol=0.01 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=True atol=0.01 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=True atol=0.1 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=True atol=0.1 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=False atol=0.001 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=False atol=0.001 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=False atol=0.01 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=False atol=0.01 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=False atol=0.1 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Flat fit=False atol=0.1 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=True atol=0.001 ang=1.0": {
"n": 0,
"solid": false
},
"blend=True cap=Round fit=True atol=0.001 ang=5.0": {
"n": 0,
"solid": false
},
"blend=True cap=Round fit=True atol=0.01 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=True atol=0.01 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=True atol=0.1 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=True atol=0.1 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=False atol=0.001 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=False atol=0.001 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=False atol=0.01 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=False atol=0.01 ang=5.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=False atol=0.1 ang=1.0": {
"n": 1,
"solid": true
},
"blend=True cap=Round fit=False atol=0.1 ang=5.0": {
"n": 1,
"solid": true
}
},
"nurbs_pipe": {
"n": 0,
"solid": false
},
"turn_planes": [
[
1.0,
0.0,
0.0,
90.0
],
[
1.0,
0.0,
-0.0,
3.81
],
[
1.0,
0.0,
0.0,
86.19
],
[
1.0,
0.0,
0.0,
90.0
],
[
1.0,
-0.0,
0.0,
90.0
]
]
},
"done": true
}
@@ -0,0 +1,69 @@
{
"before(수정2)": {
"concrete_layers": {
"P1::코핑": 1,
"P1::기둥": 1,
"P1::말뚝": 2
},
"bars": {
"P3": {
"n": 108,
"bars_with_part_outside_concrete": 0,
"max_outside_length_mm": 0.0,
"min_centre_cover_inside_mm": 2.1,
"where": [
"P1-RC-P3-L47X",
874,
0,
57450
]
},
"P3-1": {
"n": 48,
"bars_with_part_outside_concrete": 0,
"max_outside_length_mm": 0.0,
"min_centre_cover_inside_mm": 0.1,
"where": [
"P1-RC-P3-1-L13X",
-1068,
0,
40252
]
}
}
},
"after(수정5)": {
"concrete_layers": {
"P1::코핑": 1,
"P1::기둥": 1,
"P1::말뚝": 2
},
"bars": {
"P3": {
"n": 108,
"bars_with_part_outside_concrete": 0,
"max_outside_length_mm": 0.0,
"min_centre_cover_inside_mm": 0.1,
"where": [
"P1-RC-P3-L07Y",
0,
976,
45452
]
},
"P3-1": {
"n": 48,
"bars_with_part_outside_concrete": 26,
"max_outside_length_mm": 195.1,
"min_centre_cover_inside_mm": 0.0,
"where": [
"P1-RC-P3-1-L13X",
-1068,
0,
40252
]
}
}
},
"done": true
}
@@ -0,0 +1,621 @@
{
"concrete_solids": [
{
"layer": "P1::솔플레이트",
"name": "P1-SP02",
"bbox": [
1726,
-565,
60617,
2774,
565,
60695
],
"vol": 0.04
},
{
"layer": "P1::교량받침",
"name": "P1-BB02",
"bbox": [
1783,
-508,
60427,
2717,
508,
60617
],
"vol": 0.14
},
{
"layer": "P1::솔플레이트",
"name": "P1-SP01",
"bbox": [
-2746,
-541,
60302,
-1754,
541,
60380
],
"vol": 0.05
},
{
"layer": "P1::교량받침",
"name": "P1-BB01",
"bbox": [
-2692,
-487,
60112,
-1808,
487,
60302
],
"vol": 0.14
},
{
"layer": "P1::받침패드",
"name": "P1-BP02",
"bbox": [
1669,
-623,
60377,
2831,
623,
60427
],
"vol": 0.05
},
{
"layer": "P1::받침대좌",
"name": "P1-BS02",
"bbox": [
1497,
-795,
60267,
3003,
795,
60377
],
"vol": 0.2
},
{
"layer": "P1::받침패드",
"name": "P1-BP01",
"bbox": [
-2801,
-596,
60062,
-1699,
596,
60112
],
"vol": 0.05
},
{
"layer": "P1::받침대좌",
"name": "P1-BS01",
"bbox": [
-2965,
-760,
59952,
-1535,
760,
60062
],
"vol": 0.2
},
{
"layer": "P1::코핑",
"name": "P1-CP",
"bbox": [
-3800,
-1100,
57452,
3800,
1100,
60267
],
"vol": 31.39
},
{
"layer": "P1::기둥",
"name": "P1-CL",
"bbox": [
-1000,
-1000,
45452,
1000,
1000,
57452
],
"vol": 37.7
},
{
"layer": "P1::말뚝",
"name": "P1-PL02",
"bbox": [
-1250,
-1250,
40252,
1250,
1250,
45452
],
"vol": 25.53
},
{
"layer": "P1::말뚝",
"name": "P1-PL01",
"bbox": [
-1175,
-1175,
32752,
1175,
1175,
40252
],
"vol": 32.53
}
],
"bars": [
[
"P1-RC-P3-1-L01X",
-1068,
1247,
32962,
0,
61
],
[
"P1-RC-P3-1-L01Y",
0,
0,
32978,
0,
61
],
[
"P1-RC-P3-1-L02X",
-1247,
1068,
33562,
0,
61
],
[
"P1-RC-P3-1-L02Y",
0,
0,
33578,
0,
61
],
[
"P1-RC-P3-1-L03X",
-1068,
1247,
34162,
0,
61
],
[
"P1-RC-P3-1-L03Y",
0,
0,
34178,
0,
61
],
[
"P1-RC-P3-1-L04X",
-1247,
1068,
34762,
0,
61
],
[
"P1-RC-P3-1-L04Y",
0,
0,
34778,
0,
61
],
[
"P1-RC-P3-1-L05X",
-1068,
1247,
35362,
0,
61
],
[
"P1-RC-P3-1-L05Y",
0,
0,
35378,
0,
61
],
[
"P1-RC-P3-1-L06X",
-1247,
1068,
35962,
0,
61
],
[
"P1-RC-P3-1-L06Y",
0,
0,
35978,
0,
61
],
[
"P1-RC-P3-1-L07X",
-1068,
1247,
36562,
0,
61
],
[
"P1-RC-P3-1-L07Y",
0,
0,
36578,
0,
61
],
[
"P1-RC-P3-1-L08X",
-1247,
1068,
37162,
0,
61
],
[
"P1-RC-P3-1-L08Y",
0,
0,
37178,
0,
61
],
[
"P1-RC-P3-1-L09X",
-1068,
1247,
37762,
0,
61
],
[
"P1-RC-P3-1-L09Y",
0,
0,
37778,
0,
61
],
[
"P1-RC-P3-1-L10X",
-1247,
1068,
38362,
0,
61
],
[
"P1-RC-P3-1-L10Y",
0,
0,
38378,
0,
61
],
[
"P1-RC-P3-1-L11X",
-1068,
1247,
38962,
0,
61
],
[
"P1-RC-P3-1-L11Y",
0,
0,
38978,
0,
61
],
[
"P1-RC-P3-1-L12X",
-1247,
1068,
39562,
0,
61
],
[
"P1-RC-P3-1-L12Y",
0,
0,
39578,
0,
61
],
[
"P1-RC-P3-1-L13X",
-1068,
1247,
40162,
0,
61
],
[
"P1-RC-P3-1-L13Y",
0,
0,
40178,
0,
61
],
[
"P1-RC-P3-1-L14X",
-1247,
1068,
40762,
0,
61
],
[
"P1-RC-P3-1-L14Y",
0,
0,
40778,
0,
61
],
[
"P1-RC-P3-1-L15X",
-1068,
1247,
41362,
0,
61
],
[
"P1-RC-P3-1-L15Y",
0,
0,
41378,
0,
61
],
[
"P1-RC-P3-1-L16X",
-1247,
1068,
41962,
0,
61
],
[
"P1-RC-P3-1-L16Y",
0,
0,
41978,
0,
61
],
[
"P1-RC-P3-1-L17X",
-1068,
1247,
42562,
0,
61
],
[
"P1-RC-P3-1-L17Y",
0,
0,
42578,
0,
61
],
[
"P1-RC-P3-1-L18X",
-1247,
1068,
43162,
0,
61
],
[
"P1-RC-P3-1-L18Y",
0,
0,
43178,
0,
61
],
[
"P1-RC-P3-1-L19X",
-1068,
1247,
43462,
0,
61
],
[
"P1-RC-P3-1-L19Y",
0,
0,
43478,
0,
61
],
[
"P1-RC-P3-1-L20X",
-1247,
1068,
43762,
0,
61
],
[
"P1-RC-P3-1-L20Y",
0,
0,
43778,
0,
61
],
[
"P1-RC-P3-1-L21X",
-1068,
1247,
44062,
0,
61
],
[
"P1-RC-P3-1-L21Y",
0,
0,
44078,
0,
61
],
[
"P1-RC-P3-1-L22X",
-1247,
1068,
44362,
0,
61
],
[
"P1-RC-P3-1-L22Y",
0,
0,
44378,
0,
61
],
[
"P1-RC-P3-1-L23X",
-1068,
1247,
44662,
0,
61
],
[
"P1-RC-P3-1-L23Y",
0,
0,
44678,
0,
61
],
[
"P1-RC-P3-1-L24X",
-1247,
1068,
44962,
0,
61
],
[
"P1-RC-P3-1-L24Y",
0,
0,
44978,
0,
61
]
],
"column_surface_radius_probe": [
[
"P1-RC-P3-1-L01X",
33062,
0,
[]
],
[
"P1-RC-P3-1-L01X",
33062,
90,
[]
],
[
"P1-RC-P3-1-L01Y",
33078,
0,
[]
],
[
"P1-RC-P3-1-L01Y",
33078,
90,
[]
],
[
"P1-RC-P3-1-L02X",
33662,
0,
[]
],
[
"P1-RC-P3-1-L02X",
33662,
90,
[]
],
[
"P1-RC-P3-1-L02Y",
33678,
0,
[]
],
[
"P1-RC-P3-1-L02Y",
33678,
90,
[]
],
[
"P1-RC-P3-1-L03X",
34262,
0,
[]
],
[
"P1-RC-P3-1-L03X",
34262,
90,
[]
],
[
"P1-RC-P3-1-L03Y",
34278,
0,
[]
],
[
"P1-RC-P3-1-L03Y",
34278,
90,
[]
]
],
"done": true
}
@@ -0,0 +1,111 @@
{
"before": {
"P3-1": {
"PL02": {
"bars": 24,
"bars_pipe_sticks_out(cover<8)": 0,
"bars_center_outside": 0,
"min_radial_centre_cover": 181.5,
"worst": [
"P1-RC-P3-1-L24Y",
0,
1068,
45008
]
},
"PL01": {
"bars": 26,
"bars_pipe_sticks_out(cover<8)": 0,
"bars_center_outside": 0,
"min_radial_centre_cover": 106.5,
"worst": [
"P1-RC-P3-1-L13Y",
0,
-1068,
40208
]
}
},
"P3": {
"CL": {
"bars": 82,
"bars_pipe_sticks_out(cover<8)": 0,
"bars_center_outside": 0,
"min_radial_centre_cover": 84.0,
"worst": [
"P1-RC-P3-L47Y",
0,
-916,
57338
]
},
"PL02": {
"bars": 14,
"bars_pipe_sticks_out(cover<8)": 0,
"bars_center_outside": 0,
"min_radial_centre_cover": 334.0,
"worst": [
"P1-RC-P3-L07Y",
0,
-916,
45358
]
}
}
},
"after": {
"P3-1": {
"PL02": {
"bars": 24,
"bars_pipe_sticks_out(cover<8)": 22,
"bars_center_outside": 0,
"min_radial_centre_cover": 3.4,
"worst": [
"P1-RC-P3-1-L19Y",
0,
1247,
43478
]
},
"PL01": {
"bars": 26,
"bars_pipe_sticks_out(cover<8)": 26,
"bars_center_outside": 26,
"min_radial_centre_cover": -71.6,
"worst": [
"P1-RC-P3-1-L13Y",
0,
1247,
40178
]
}
},
"P3": {
"CL": {
"bars": 82,
"bars_pipe_sticks_out(cover<8)": 0,
"bars_center_outside": 0,
"min_radial_centre_cover": 24.1,
"worst": [
"P1-RC-P3-L13Y",
0,
976,
47251
]
},
"PL02": {
"bars": 14,
"bars_pipe_sticks_out(cover<8)": 0,
"bars_center_outside": 0,
"min_radial_centre_cover": 274.1,
"worst": [
"P1-RC-P3-L07Y",
0,
976,
45451
]
}
}
},
"done": true
}
@@ -0,0 +1,111 @@
{
"수정5(r135 70도)": {
"P3-1": {
"PL02": {
"bars": 24,
"bars_pipe_sticks_out(cover<8)": 22,
"bars_center_outside": 0,
"min_radial_centre_cover": 3.4,
"worst": [
"P1-RC-P3-1-L19Y",
0,
1247,
43478
]
},
"PL01": {
"bars": 26,
"bars_pipe_sticks_out(cover<8)": 26,
"bars_center_outside": 26,
"min_radial_centre_cover": -71.6,
"worst": [
"P1-RC-P3-1-L13Y",
0,
1247,
40178
]
}
},
"P3": {
"CL": {
"bars": 82,
"bars_pipe_sticks_out(cover<8)": 0,
"bars_center_outside": 0,
"min_radial_centre_cover": 24.1,
"worst": [
"P1-RC-P3-L13Y",
0,
976,
47251
]
},
"PL02": {
"bars": 14,
"bars_pipe_sticks_out(cover<8)": 0,
"bars_center_outside": 0,
"min_radial_centre_cover": 274.1,
"worst": [
"P1-RC-P3-L07Y",
0,
976,
45451
]
}
}
},
"수정6(P3 각도)": {
"P3-1": {
"PL01": {
"bars": 26,
"bars_pipe_sticks_out(cover<8)": 0,
"bars_center_outside": 0,
"min_radial_centre_cover": 36.4,
"worst": [
"P1-RC-P3-1-L09X",
1139,
0,
37917
]
},
"PL02": {
"bars": 24,
"bars_pipe_sticks_out(cover<8)": 0,
"bars_center_outside": 0,
"min_radial_centre_cover": 111.4,
"worst": [
"P1-RC-P3-1-L19Y",
0,
1139,
43633
]
}
},
"P3": {
"CL": {
"bars": 82,
"bars_pipe_sticks_out(cover<8)": 0,
"bars_center_outside": 0,
"min_radial_centre_cover": 24.1,
"worst": [
"P1-RC-P3-L13Y",
0,
976,
47251
]
},
"PL02": {
"bars": 14,
"bars_pipe_sticks_out(cover<8)": 0,
"bars_center_outside": 0,
"min_radial_centre_cover": 274.1,
"worst": [
"P1-RC-P3-L07Y",
0,
976,
45451
]
}
}
},
"done": true
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,63 @@
{
"sanoe": {
"objects_before": 2004,
"stat": {
"B7_done": 98,
"B10_done": 7,
"B9_done": 7
},
"sample": {
"B7": {
"len_old": 2401.26,
"len_new": 2465.26,
"tail_new": 80.5,
"z": [
132.5,
2414.5
]
},
"B10": {
"len_old": 7479.4,
"len_new": 7500.0,
"tail_new": 86.3,
"z": [
1164.7,
1275.0
]
},
"B9": {
"len_old": 7479.4,
"len_new": 7500.0,
"tail_new": 86.3,
"z": [
1164.7,
1275.0
]
}
},
"objects_after": 2004,
"saved": true,
"out": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\검토_산외교P1\\산외교P1 G5_수정3_20261026.3dm"
},
"okseong": {
"objects_before": 3862,
"stat": {
"B9_done": 171
},
"sample": {
"B9": {
"len_old": 4689.3,
"len_new": 4763.0,
"tail_new": 93.92,
"z": [
126.0,
2124.0
]
}
},
"objects_after": 3862,
"saved": true,
"out": "D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\검토_옥성교P1\\옥성교P1_G5_수정3_20261026.3dm"
},
"done": true
}
File diff suppressed because it is too large. Load diff
+19
View File
@@ -0,0 +1,19 @@
{
"D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\철근 모델랑 운곡교P1_바이브코딩\\운곡교p1_수정_20261023.3dm": {
"objects": 3236,
"saved": true
},
"D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\검토_산외교P1\\산외교P1 G5_수정_20261023.3dm": {
"objects": 2004,
"saved": true
},
"D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\검토_옥성교P1\\옥성교P1_G5_수정_20261023.3dm": {
"objects": 3862,
"saved": true
},
"D:\\★Pier 자료\\프로그램\\Pier_T\\검토파일\\Ramp-A교P1\\ramp-A G5_수정_20261023.3dm": {
"objects": 2255,
"saved": true
},
"done": true
}
File diff suppressed because it is too large. Load diff
+847
View File
@@ -0,0 +1,847 @@
{
"orig": {
"layers": {
"P1": {
"visible": true,
"locked": false,
"parent_visible": null
},
"P1::기초": {
"visible": true,
"locked": false,
"parent_visible": null
},
"P1::철근": {
"visible": true,
"locked": false,
"parent_visible": null
},
"P1::철근::중심선": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B2": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B4": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B6": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B8": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B3": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B7": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B1": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B5": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B11": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B12": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B10": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B9": {
"visible": false,
"locked": false,
"parent_visible": null
}
},
"objs": [
"P1::기초|shown|unlocked|layer_vis=1",
"P1::철근::기초::B1|shown|unlocked|layer_off=38",
"P1::철근::기초::B10|shown|unlocked|layer_off=9",
"P1::철근::기초::B11|shown|unlocked|layer_off=28",
"P1::철근::기초::B12|shown|unlocked|layer_off=28",
"P1::철근::기초::B2|shown|unlocked|layer_off=38",
"P1::철근::기초::B3|shown|unlocked|layer_off=38",
"P1::철근::기초::B4|shown|unlocked|layer_off=35",
"P1::철근::기초::B5|shown|unlocked|layer_off=32",
"P1::철근::기초::B6|shown|unlocked|layer_off=32",
"P1::철근::기초::B7|shown|unlocked|layer_off=32",
"P1::철근::기초::B8|shown|unlocked|layer_off=29",
"P1::철근::기초::B9|shown|unlocked|layer_off=493"
],
"bbox": {
"P1::철근::기초::B9": [
-4133.0,
-3508.0,
26327.5,
4221.0,
3508.0,
28358.9
],
"P1::철근::기초::B10": [
-4608.5,
-3831.5,
26548.5,
4608.5,
3831.5,
28167.5
],
"P1::철근::기초::B12": [
-3883.0,
-3808.0,
26658.0,
3883.0,
3808.0,
27966.0
],
"P1::철근::기초::B11": [
-4583.0,
-3258.0,
26658.0,
4583.0,
3258.0,
27966.0
],
"P1::철근::기초::B5": [
-4589.5,
-3814.5,
28135.0,
4589.5,
3814.5,
28349.5
],
"P1::철근::기초::B1": [
-4587.5,
-3812.5,
28081.0,
4587.5,
3812.5,
28293.5
],
"P1::철근::기초::B7": [
-4584.5,
-3809.5,
26475.5,
4584.5,
3809.5,
26685.0
],
"P1::철근::기초::B3": [
-4584.5,
-3809.5,
26426.0,
4584.5,
3809.5,
26635.5
],
"P1::철근::기초::B6": [
-4589.5,
-3814.5,
26371.5,
4589.5,
3814.5,
28336.0
],
"P1::철근::기초::B8": [
-4575.0,
-3514.5,
26371.5,
4575.0,
3514.5,
26400.5
],
"P1::철근::기초::B2": [
-4587.5,
-3812.5,
26317.5,
4587.5,
3812.5,
28280.0
],
"P1::철근::기초::B4": [
-4262.5,
-3800.0,
26317.5,
4262.5,
3800.0,
26342.5
],
"P1::기초": [
-4675.0,
-3900.0,
26208.0,
4675.0,
3900.0,
28408.0
]
},
"cplane": null
},
"reviewed": {
"layers": {
"P1": {
"visible": true,
"locked": false,
"parent_visible": null
},
"P1::기초": {
"visible": true,
"locked": false,
"parent_visible": null
},
"P1::철근": {
"visible": true,
"locked": false,
"parent_visible": null
},
"P1::철근::중심선": {
"visible": true,
"locked": false,
"parent_visible": null
},
"P1::철근::기초": {
"visible": true,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B2": {
"visible": true,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B4": {
"visible": true,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B6": {
"visible": true,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B8": {
"visible": true,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B3": {
"visible": true,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B7": {
"visible": true,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B1": {
"visible": true,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B5": {
"visible": true,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B11": {
"visible": true,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B12": {
"visible": true,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B10": {
"visible": true,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B9": {
"visible": true,
"locked": false,
"parent_visible": null
}
},
"objs": [
"P1::기초|shown|unlocked|layer_vis=1",
"P1::철근::기초::B1|shown|unlocked|layer_vis=38",
"P1::철근::기초::B10|shown|unlocked|layer_vis=9",
"P1::철근::기초::B11|shown|unlocked|layer_vis=28",
"P1::철근::기초::B12|shown|unlocked|layer_vis=28",
"P1::철근::기초::B2|shown|unlocked|layer_vis=38",
"P1::철근::기초::B3|shown|unlocked|layer_vis=38",
"P1::철근::기초::B4|shown|unlocked|layer_vis=35",
"P1::철근::기초::B5|shown|unlocked|layer_vis=32",
"P1::철근::기초::B6|shown|unlocked|layer_vis=32",
"P1::철근::기초::B7|shown|unlocked|layer_vis=32",
"P1::철근::기초::B8|shown|unlocked|layer_vis=29",
"P1::철근::기초::B9|shown|unlocked|layer_vis=493"
],
"bbox": {
"P1::철근::기초::B9": [
-4133.0,
-3508.0,
26327.5,
4221.0,
3508.0,
28358.9
],
"P1::철근::기초::B10": [
-4608.5,
-3831.5,
26548.5,
4608.5,
3831.5,
28167.5
],
"P1::철근::기초::B12": [
-3883.0,
-3808.0,
26658.0,
3883.0,
3808.0,
27966.0
],
"P1::철근::기초::B11": [
-4583.0,
-3258.0,
26658.0,
4583.0,
3258.0,
27966.0
],
"P1::철근::기초::B5": [
-4589.5,
-3814.5,
28135.0,
4589.5,
3814.5,
28349.5
],
"P1::철근::기초::B1": [
-4587.5,
-3812.5,
28081.0,
4587.5,
3812.5,
28293.5
],
"P1::철근::기초::B7": [
-4584.5,
-3809.5,
26475.5,
4584.5,
3809.5,
26685.0
],
"P1::철근::기초::B3": [
-4584.5,
-3809.5,
26426.0,
4584.5,
3809.5,
26635.5
],
"P1::철근::기초::B6": [
-4589.5,
-3814.5,
26371.5,
4589.5,
3814.5,
28336.0
],
"P1::철근::기초::B8": [
-4575.0,
-3514.5,
26371.5,
4575.0,
3514.5,
26400.5
],
"P1::철근::기초::B2": [
-4587.5,
-3812.5,
26317.5,
4587.5,
3812.5,
28280.0
],
"P1::철근::기초::B4": [
-4262.5,
-3800.0,
26317.5,
4262.5,
3800.0,
26342.5
],
"P1::기초": [
-4675.0,
-3900.0,
26208.0,
4675.0,
3900.0,
28408.0
]
},
"cplane": null
},
"mod1": {
"layers": {
"P1": {
"visible": true,
"locked": false,
"parent_visible": null
},
"P1::기초": {
"visible": true,
"locked": false,
"parent_visible": null
},
"P1::철근": {
"visible": true,
"locked": false,
"parent_visible": null
},
"P1::철근::중심선": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B2": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B4": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B6": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B8": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B3": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B7": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B1": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B5": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B11": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B12": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B10": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B9": {
"visible": false,
"locked": false,
"parent_visible": null
}
},
"objs": [
"P1::기초|shown|unlocked|layer_vis=1",
"P1::철근::기초::B1|shown|unlocked|layer_off=38",
"P1::철근::기초::B10|shown|unlocked|layer_off=9",
"P1::철근::기초::B11|shown|unlocked|layer_off=28",
"P1::철근::기초::B12|shown|unlocked|layer_off=28",
"P1::철근::기초::B2|shown|unlocked|layer_off=38",
"P1::철근::기초::B3|shown|unlocked|layer_off=38",
"P1::철근::기초::B4|shown|unlocked|layer_off=35",
"P1::철근::기초::B5|shown|unlocked|layer_off=32",
"P1::철근::기초::B6|shown|unlocked|layer_off=32",
"P1::철근::기초::B7|shown|unlocked|layer_off=32",
"P1::철근::기초::B8|shown|unlocked|layer_off=29",
"P1::철근::기초::B9|shown|unlocked|layer_off=493"
],
"bbox": {
"P1::철근::기초::B9": [
-4133.0,
-3508.0,
26327.5,
4221.0,
3508.0,
28358.9
],
"P1::철근::기초::B10": [
-4608.5,
-3831.5,
26548.5,
4608.5,
3831.5,
28167.5
],
"P1::철근::기초::B12": [
-3883.0,
-3808.0,
26658.0,
3883.0,
3808.0,
27966.0
],
"P1::철근::기초::B11": [
-4583.0,
-3258.0,
26658.0,
4583.0,
3258.0,
27966.0
],
"P1::철근::기초::B5": [
-4589.5,
-3814.5,
28135.0,
4589.5,
3814.5,
28349.5
],
"P1::철근::기초::B1": [
-4587.5,
-3812.5,
28081.0,
4587.5,
3812.5,
28293.5
],
"P1::철근::기초::B7": [
-4584.5,
-3809.5,
26475.5,
4584.5,
3809.5,
26685.0
],
"P1::철근::기초::B3": [
-4584.5,
-3809.5,
26426.0,
4584.5,
3809.5,
26635.5
],
"P1::철근::기초::B6": [
-4589.5,
-3814.5,
26371.5,
4589.5,
3814.5,
28336.0
],
"P1::철근::기초::B8": [
-4575.0,
-3514.5,
26371.5,
4575.0,
3514.5,
26400.5
],
"P1::철근::기초::B2": [
-4587.5,
-3812.5,
26317.5,
4587.5,
3812.5,
28280.0
],
"P1::철근::기초::B4": [
-4262.5,
-3800.0,
26317.5,
4262.5,
3800.0,
26342.5
],
"P1::기초": [
-4675.0,
-3900.0,
26208.0,
4675.0,
3900.0,
28408.0
]
},
"cplane": null
},
"mod2": {
"layers": {
"P1": {
"visible": true,
"locked": false,
"parent_visible": null
},
"P1::기초": {
"visible": true,
"locked": false,
"parent_visible": null
},
"P1::철근": {
"visible": true,
"locked": false,
"parent_visible": null
},
"P1::철근::중심선": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B2": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B4": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B6": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B8": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B3": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B7": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B1": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B5": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B11": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B12": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B10": {
"visible": false,
"locked": false,
"parent_visible": null
},
"P1::철근::기초::B9": {
"visible": false,
"locked": false,
"parent_visible": null
}
},
"objs": [
"P1::기초|shown|unlocked|layer_vis=1",
"P1::철근::기초::B1|shown|unlocked|layer_off=38",
"P1::철근::기초::B10|shown|unlocked|layer_off=9",
"P1::철근::기초::B11|shown|unlocked|layer_off=28",
"P1::철근::기초::B12|shown|unlocked|layer_off=28",
"P1::철근::기초::B2|shown|unlocked|layer_off=38",
"P1::철근::기초::B3|shown|unlocked|layer_off=38",
"P1::철근::기초::B4|shown|unlocked|layer_off=35",
"P1::철근::기초::B5|shown|unlocked|layer_off=32",
"P1::철근::기초::B6|shown|unlocked|layer_off=32",
"P1::철근::기초::B7|shown|unlocked|layer_off=32",
"P1::철근::기초::B8|shown|unlocked|layer_off=29",
"P1::철근::기초::B9|shown|unlocked|layer_off=493"
],
"bbox": {
"P1::철근::기초::B4": [
-4262.5,
-3800.0,
26345.5,
4262.5,
3800.0,
26370.5
],
"P1::철근::기초::B2": [
-4587.5,
-3812.5,
26358.0,
4587.5,
3812.5,
28308.0
],
"P1::철근::기초::B8": [
-4575.0,
-3514.5,
26343.5,
4575.0,
3514.5,
26372.5
],
"P1::철근::기초::B6": [
-4589.5,
-3814.5,
26343.5,
4589.5,
3814.5,
28308.0
],
"P1::철근::기초::B3": [
-4584.5,
-3809.5,
26435.5,
4584.5,
3809.5,
26635.5
],
"P1::철근::기초::B7": [
-4584.5,
-3809.5,
26475.5,
4584.5,
3809.5,
26685.0
],
"P1::철근::기초::B1": [
-4587.5,
-3812.5,
28108.0,
4587.5,
3812.5,
28308.0
],
"P1::철근::기초::B5": [
-4589.5,
-3814.5,
28108.0,
4589.5,
3814.5,
28322.5
],
"P1::철근::기초::B10": [
-4608.5,
-3831.5,
26548.5,
4608.5,
3831.5,
28167.5
],
"P1::철근::기초::B9": [
-4133.0,
-3508.0,
26327.5,
4221.0,
3508.0,
28358.9
],
"P1::철근::기초::B12": [
-3883.0,
-3808.0,
26658.0,
3883.0,
3808.0,
27966.0
],
"P1::철근::기초::B11": [
-4583.0,
-3258.0,
26658.0,
4583.0,
3258.0,
27966.0
],
"P1::기초": [
-4675.0,
-3900.0,
26208.0,
4675.0,
3900.0,
28408.0
]
},
"cplane": null
},
"done": true
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

@@ -0,0 +1,40 @@
{
"key": "hookA_p3",
"png": "C:\\Users\\User\\AppData\\Local\\PierApp\\jobs\\cap\\out\\hookA_p3.png",
"size": [
1500,
835
],
"px": {
"arc_start": [
736.130090187417,
258.3189661928836
],
"arc_end": [
814.5233222741133,
445.93130737328494
],
"center": [
736.1300901874268,
368.50332064437737
],
"tail_end": [
685.4766777258866,
576.5866941844455
],
"leg_end": [
-2628.165532398545,
625.6001476978923
],
"vertex": [
-2584.0917906179434,
258.3189661928836
]
},
"radius": 59.999999999992724,
"angle_deg": 134.64508185575693,
"arc_len": 140.99999999999702,
"tail_len": 100.00000000000243,
"pxmm": 1.8364059075250874,
"done": true
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

@@ -0,0 +1,40 @@
{
"key": "hookB_p31",
"png": "C:\\Users\\User\\AppData\\Local\\PierApp\\jobs\\cap\\out\\hookB_p31.png",
"size": [
1500,
835
],
"px": {
"arc_start": [
606.1405543878883,
231.79292747337078
],
"arc_end": [
811.0987992599386,
375.38134971283836
],
"center": [
606.1405543878961,
449.86593142979194
],
"tail_end": [
893.8594456121115,
603.1127329040024
],
"leg_end": [
-2845.8743304630307,
554.8640444458509
],
"vertex": [
-2807.1057964263337,
231.79292747337078
]
},
"radius": 135.0,
"angle_deg": 70.0281749604329,
"arc_len": 164.99999999999756,
"tail_len": 150.00000000000153,
"pxmm": 1.6153555848623864,
"done": true
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

@@ -0,0 +1,40 @@
{
"key": "hookC_p31",
"png": "C:\\Users\\User\\AppData\\Local\\PierApp\\jobs\\cap\\out\\hookC_p31.png",
"size": [
1500,
835
],
"px": {
"arc_start": [
754.4748045566357,
233.28770741716656
],
"arc_end": [
835.7913628675209,
427.896214750599
],
"center": [
754.4748045566396,
347.5808963214267
],
"tail_end": [
664.2086371324787,
601.6179529601992
],
"leg_end": [
-2724.159619793393,
558.8501242959705
],
"vertex": [
-2685.0921297679365,
233.28770741716656
]
},
"radius": 70.21276595744712,
"angle_deg": 134.64508185573948,
"arc_len": 164.99999999999585,
"tail_len": 149.99999999999824,
"pxmm": 1.6278120843940247,
"done": true
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

@@ -0,0 +1,78 @@
{
"tag": "lap_after",
"items": {
"C7": {
"png": "C:\\Users\\User\\AppData\\Local\\PierApp\\jobs\\cap\\out\\lap_after_C7.png",
"base": "P1-R-C7-x-3000_1",
"pieces": 2,
"size": [
1500,
835
],
"view": "Right",
"bbox": [
-3011.0,
-1011.002352924502,
68727.62654771376,
-2989.0,
1011.0028746353098,
71119.5
]
},
"C10": {
"png": "C:\\Users\\User\\AppData\\Local\\PierApp\\jobs\\cap\\out\\lap_after_C10.png",
"base": "P1-R-C10-L10",
"pieces": 2,
"size": [
1500,
835
],
"view": "Top",
"bbox": [
-3004.1036686230273,
-1488.5030346934693,
68751.49999999996,
3004.103668623548,
1488.5054489682186,
68773.50000000006
]
},
"C12": {
"png": "C:\\Users\\User\\AppData\\Local\\PierApp\\jobs\\cap\\out\\lap_after_C12.png",
"base": "P1-R-C12-L04",
"pieces": 2,
"size": [
1500,
835
],
"view": "Top",
"bbox": [
-4835.7031667338,
-1488.51377992829,
69951.49999999996,
4829.003166733801,
1488.5043954640673,
69973.50000000004
]
},
"C13": {
"png": "C:\\Users\\User\\AppData\\Local\\PierApp\\jobs\\cap\\out\\lap_after_C13.png",
"base": "P1-R-C13-L03y-272",
"pieces": 2,
"size": [
1500,
835
],
"view": "Top",
"bbox": [
-4776.901156384916,
-283.5,
70151.5,
4767.101150556827,
-118.5,
70173.5
]
}
},
"done": true
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

@@ -0,0 +1,78 @@
{
"tag": "lap_before",
"items": {
"C7": {
"png": "C:\\Users\\User\\AppData\\Local\\PierApp\\jobs\\cap\\out\\lap_before_C7.png",
"base": "P1-R-C7-x-3000_1",
"pieces": 1,
"size": [
1500,
835
],
"view": "Right",
"bbox": [
-3010.9999999999995,
-1011.0003152618904,
68727.62968546397,
-2989.0000000000005,
1011.0003024106404,
71130.50030725572
]
},
"C10": {
"png": "C:\\Users\\User\\AppData\\Local\\PierApp\\jobs\\cap\\out\\lap_before_C10.png",
"base": "P1-R-C10-L10",
"pieces": 1,
"size": [
1500,
835
],
"view": "Top",
"bbox": [
-3004.1021444995094,
-1488.5007119235188,
68751.49999999996,
3004.1019569047417,
1488.5007771340609,
68773.50000000004
]
},
"C12": {
"png": "C:\\Users\\User\\AppData\\Local\\PierApp\\jobs\\cap\\out\\lap_before_C12.png",
"base": "P1-R-C12-L04",
"pieces": 1,
"size": [
1500,
835
],
"view": "Top",
"bbox": [
-4835.700001208581,
-1488.5000012085638,
69951.49999999997,
4829.000001208581,
1488.5000012086114,
69973.50000000003
]
},
"C13": {
"png": "C:\\Users\\User\\AppData\\Local\\PierApp\\jobs\\cap\\out\\lap_before_C13.png",
"base": "P1-R-C13-L03y-272",
"pieces": 1,
"size": [
1500,
835
],
"view": "Top",
"bbox": [
-4798.9,
-283.5,
70151.5,
4789.1,
-118.5,
70173.5
]
}
},
"done": true
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

@@ -0,0 +1,123 @@
{
"key": "okseong",
"doc": "C:\\Users\\User\\AppData\\Local\\PierApp\\jobs\\cap\\okseong.3dm",
"footing_bbox": [
-4800.0,
-4800.0,
12175.0,
4800.0,
4800.0,
14375.0
],
"views": {
"Front": {
"png": "C:\\Users\\User\\AppData\\Local\\PierApp\\jobs\\cap\\out\\okseong_Front.png",
"size": [
1800,
1002
],
"client": [
742,
413
],
"scale": 2.4258760107816713,
"lines": {
"B1·B3 상면 100 (z2100)": [
[
129.94652406417111,
340.5155887397844
],
[
1670.053475935829,
340.5155887397844
]
],
"B5·B7 (z2071)": [
[
129.94652406417111,
345.1679951568966
],
[
1670.053475935829,
345.1679951568966
]
],
"B6·B8 (z179)": [
[
129.94652406417111,
648.6974069216025
],
[
1670.053475935829,
648.6974069216025
]
],
"B2·B4 하면 150 (z150)": [
[
129.94652406417111,
653.3498133387147
],
[
1670.053475935829,
653.3498133387147
]
]
}
},
"Right": {
"png": "C:\\Users\\User\\AppData\\Local\\PierApp\\jobs\\cap\\out\\okseong_Right.png",
"size": [
1800,
1002
],
"client": [
742,
413
],
"scale": 2.4258760107816713,
"lines": {
"B1·B3 상면 100 (z2100)": [
[
129.94652406417111,
340.5155887397844
],
[
1670.053475935829,
340.5155887397844
]
],
"B5·B7 (z2071)": [
[
129.94652406417111,
345.1679951568966
],
[
1670.053475935829,
345.1679951568966
]
],
"B6·B8 (z179)": [
[
129.94652406417111,
648.6974069216025
],
[
1670.053475935829,
648.6974069216025
]
],
"B2·B4 하면 150 (z150)": [
[
129.94652406417111,
653.3498133387147
],
[
1670.053475935829,
653.3498133387147
]
]
}
}
},
"done": true
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

@@ -0,0 +1,37 @@
{
"key": "p32_ramp3",
"png": "C:\\Users\\User\\AppData\\Local\\PierApp\\jobs\\cap\\out\\p32_ramp3.png",
"size": [
1500,
835
],
"T1": [
184.38593886798566,
204.14735171170784
],
"T2": [
1315.6140616924683,
204.14735171170784
],
"C1": [
184.38593886798566,
626.343759893663
],
"C2": [
1315.6140616924683,
626.343759893663
],
"T1_world": [
1016.5147995707109,
-131.61558514749493,
33617.1
],
"T2_world": [
-1016.5147995707109,
131.61558514749493,
33617.1
],
"zb": 32852.0,
"zt": 33617.1,
"done": true
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

@@ -0,0 +1,37 @@
{
"key": "p32_ramp4",
"png": "C:\\Users\\User\\AppData\\Local\\PierApp\\jobs\\cap\\out\\p32_ramp4.png",
"size": [
1500,
835
],
"T1": [
184.38603528216942,
237.00777064519235
],
"T2": [
1315.6136958370369,
237.00777064519235
],
"C1": [
184.38603528216942,
593.4824383127265
],
"C2": [
1315.6136958370369,
593.4824383127265
],
"T1_world": [
1016.5147995707109,
-131.61558514749493,
33498.0
],
"T2_world": [
-1016.5147995707109,
131.61558514749493,
33498.0
],
"zb": 32852.0,
"zt": 33498.0,
"done": true
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

@@ -0,0 +1,123 @@
{
"key": "sanoe",
"doc": "C:\\Users\\User\\AppData\\Local\\PierApp\\jobs\\cap\\sanoe.3dm",
"footing_bbox": [
-3750.0,
-3750.0,
42763.0,
3750.0,
3750.0,
45263.0
],
"views": {
"Front": {
"png": "C:\\Users\\User\\AppData\\Local\\PierApp\\jobs\\cap\\out\\sanoe_Front.png",
"size": [
1800,
1002
],
"client": [
742,
413
],
"scale": 2.4258760107816713,
"lines": {
"B1 상면 100 (z2400)": [
[
142.4242424242424,
268.62016390318246
],
[
1657.5757575757577,
268.62016390318246
]
],
"B4 (z2384)": [
[
142.4242424242424,
271.8524871355059
],
[
1657.5757575757577,
271.8524871355059
]
],
"B5·B6 (z172)": [
[
142.4242424242424,
718.7211740041924
],
[
1657.5757575757577,
718.7211740041924
]
],
"B2·B3 하면 150 (z150)": [
[
142.4242424242424,
723.1656184486366
],
[
1657.5757575757577,
723.1656184486366
]
]
}
},
"Right": {
"png": "C:\\Users\\User\\AppData\\Local\\PierApp\\jobs\\cap\\out\\sanoe_Right.png",
"size": [
1800,
1002
],
"client": [
742,
413
],
"scale": 2.4258760107816713,
"lines": {
"B1 상면 100 (z2400)": [
[
142.4242424242424,
268.62016390318246
],
[
1657.5757575757577,
268.62016390318246
]
],
"B4 (z2384)": [
[
142.4242424242424,
271.8524871355059
],
[
1657.5757575757577,
271.8524871355059
]
],
"B5·B6 (z172)": [
[
142.4242424242424,
718.7211740041924
],
[
1657.5757575757577,
718.7211740041924
]
],
"B2·B3 하면 150 (z150)": [
[
142.4242424242424,
723.1656184486366
],
[
1657.5757575757577,
723.1656184486366
]
]
}
}
},
"done": true
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

@@ -0,0 +1,123 @@
{
"key": "ungok",
"doc": "C:\\Users\\User\\AppData\\Local\\PierApp\\jobs\\cap\\ungok.3dm",
"footing_bbox": [
-4675.0,
-3900.0,
26208.0,
4675.0,
3900.0,
28408.0
],
"views": {
"Front": {
"png": "C:\\Users\\User\\AppData\\Local\\PierApp\\jobs\\cap\\out\\ungok_Front.png",
"size": [
1800,
1002
],
"client": [
742,
413
],
"scale": 2.4258760107816713,
"lines": {
"B5 상면 100 (z2100)": [
[
131.1557788944723,
336.48473930544634
],
[
1668.8442211055278,
336.48473930544634
]
],
"B1 (z2072.5)": [
[
131.1557788944723,
341.0073523707735
],
[
1668.8442211055278,
341.0073523707735
]
],
"B2·B4 (z177)": [
[
131.1557788944723,
652.7387365644691
],
[
1668.8442211055278,
652.7387365644691
]
],
"B6·B8 하면 150 (z150)": [
[
131.1557788944723,
657.1791203013352
],
[
1668.8442211055278,
657.1791203013352
]
]
}
},
"Right": {
"png": "C:\\Users\\User\\AppData\\Local\\PierApp\\jobs\\cap\\out\\ungok_Right.png",
"size": [
1800,
1002
],
"client": [
742,
413
],
"scale": 2.4258760107816713,
"lines": {
"B5 상면 100 (z2100)": [
[
140.25974025974025,
306.13820142122097
],
[
1659.74025974026,
306.13820142122097
]
],
"B1 (z2072.5)": [
[
140.25974025974025,
311.4953442783642
],
[
1659.74025974026,
311.4953442783642
]
],
"B2·B4 (z177)": [
[
140.25974025974025,
680.7485910316113
],
[
1659.74025974026,
680.7485910316113
]
],
"B6·B8 하면 150 (z150)": [
[
140.25974025974025,
686.0083312913506
],
[
1659.74025974026,
686.0083312913506
]
]
}
}
},
"done": true
}
@@ -0,0 +1,58 @@
"""산외교 기초 B1·B4 재료표↔형상 대조 결과(수정 없음, 2026-10-27)를 엑셀에 기록. 백업(양쪽) → Pier_T 사본 → 원본 복사 → SHA 확인."""
import copy, datetime, hashlib, shutil, sys
from pathlib import Path
import openpyxl
from openpyxl.drawing.image import Image as XLImage
from openpyxl.styles import Alignment, PatternFill
ROOT = Path(r"D:\★Pier 자료\프로그램\Pier_T"); REV = ROOT / "검토파일"; ORIG = Path(r"D:\★Pier 자료\심수석님 검토 파일"); NAME = "4개교_공통사항_종합.xlsx"
stamp = datetime.date.today().strftime("%Y%m%d")
for d in (REV, ORIG):
shutil.copy2(d / NAME, d / ("4개교_공통사항_종합_백업_%s_B1B4대조.xlsx" % stamp))
wb = openpyxl.load_workbook(REV / NAME)
ws = wb["수정 내역"]
if any(r[0].value == "R-20" for r in ws.iter_rows(min_row=4)):
sys.exit("R-20 이미 있음")
GREEN = PatternFill("solid", fgColor="FFE2EFDA"); YEL = PatternFill("solid", fgColor="FFFFF2CC")
def append_like(sheet, values, like_row):
r = sheet.max_row + 1
for j, v in enumerate(values, 1):
c = sheet.cell(row=r, column=j, value=v); s = sheet.cell(row=like_row, column=j)
c.font = copy.copy(s.font); c.fill = copy.copy(s.fill); c.border = copy.copy(s.border); c.alignment = copy.copy(s.alignment); c.number_format = s.number_format
sheet.auto_filter.ref = "A3:%s%d" % (openpyxl.utils.get_column_letter(sheet.max_column), r)
return r
r = append_like(ws, ["R-20", "산외교", "기초 B1·B4 재료표↔형상 대조 (사용자 지적: ㄷ자철근 아니냐) — 결과: 수정 없음",
"B1·B4 (H16, 형식 I, 31본씩)",
"모델 직선 1본 7,300 (재료표 A=7,300, B 칸 없음, 길이 7,300 과 일치)",
"변경 없음. 도면 형상 상세가 강종별로 두 벌: SD500 형식 I = 직선(a 만), SD400 형식 I = ㄷ자(a+b 다리). B1·B4 는 SD500 재료표 → 직선",
0,
"사용자 지적 2026-10-27(SD400 상세 그림 제시). 지금까지 SD400·SD500 상세를 구분해 대조하지 않았음(재료표 숫자 위주) — 보완",
"산외교P1 G5_수정5_20261027.3dm (변경 없음)",
"재료표 행·SD500 상세·SD400 상세·모델 캡처를 한 장에 대조(공통 문제 상세 27행). B1·B4 모델은 직선 7,300 으로 도면과 일치",
"B1·B4 를 ㄷ자로 봐야 하면 b 값이 도면에 없어 설계자 확인(도면 오류 기록). 4개교 기초철근 전체 재료표·형상 상세·모델 마크별 대조표는 별도 진행 예정"], 4)
ws.cell(row=r, column=1).fill = YEL
hold = wb["미수정·보류"]
append_like(hold, ["산외교", "B1·B4 형상 (H16 형식 I)", "-", "수정 없음(대조 결과 직선 일치): SD500 상세 I=직선. SD400 상세 I=ㄷ자(b)와 혼동 가능",
"사용자 의견: ㄷ자철근이라는 지적. B1·B4 가 ㄷ자라면 b 값이 도면(재료표 B 칸)에 없음. 'R-20'", "도면 상 B1·B4 형상 확인(직선 vs ㄷ자)"], 4)
fs = wb["수정 증거(마크별)"]
for m in ("B1", "B4"):
append_like(fs, ["산외교", m, "H16", "형상 대조(수정 없음)", 31, "직선 7,300", "직선 7,300 (변경 없음)", 0, "R-20. 재료표 SD500 형식 I(직선)과 일치"], 4)
wd = wb["공통 문제 상세(이미지)"]
nr = wd.max_row + 1; like = nr - 1
vals = {1: "C-4", 2: "[개별] 산외교 B1·B4 — 재료표 · 형상 상세(SD500/SD400) · 모델 대조",
7: "재료표 B1·B4: 형식 I, A 7,300, B 없음. SD500 상세 I = 직선 / SD400 상세 I = ㄷ자(b)",
8: "모델: 직선 1본 7,300 (수정5). 형상 상세를 강종별로 구분해 대조하지 않았던 점 보완",
9: "수정 없음(일치) 'R-20'. B1·B4 를 ㄷ자로 봐야 하면 b 값이 도면에 없어 설계자 확인"}
for col, v in vals.items():
c = wd.cell(row=nr, column=col, value=v); s = wd.cell(row=like, column=col)
c.font = copy.copy(s.font); c.fill = copy.copy(s.fill); c.border = copy.copy(s.border); c.alignment = Alignment(wrap_text=True, vertical="top")
wd.cell(row=nr, column=9).fill = copy.copy(YEL)
wd.row_dimensions[nr].height = 420
im = XLImage(str(REV / "수정후_캡처" / "산외교_B1B4_재료표형상_대조.png")); w0, h0 = im.width, im.height
im.width, im.height = 1000, int(1000 * h0 / w0); wd.add_image(im, "F%d" % nr)
wb.save(REV / NAME); shutil.copy2(REV / NAME, ORIG / NAME)
sha = lambda p: hashlib.sha256(Path(p).read_bytes()).hexdigest()
print("sha equal:", sha(REV / NAME) == sha(ORIG / NAME), sha(REV / NAME)[:16], "images:", len(openpyxl.load_workbook(REV / NAME)["공통 문제 상세(이미지)"]._images), "row", nr)
@@ -0,0 +1,35 @@
"""옥성 C9·C11·C13 오각형 스터럽 c=630 겹침(수정8) 기록: '수정 내역' R-25 + 이미지(형상 일람 시트 하단). 백업(양쪽) → Pier_T → 원본 복사 → SHA 확인."""
import copy, datetime, hashlib, shutil, sys
from pathlib import Path
import openpyxl
from openpyxl.drawing.image import Image as XLImage
from openpyxl.styles import Font, PatternFill
ROOT = Path(r"D:\★Pier 자료\프로그램\Pier_T"); REV = ROOT / "검토파일"; ORIG = Path(r"D:\★Pier 자료\심수석님 검토 파일"); NAME = "4개교_공통사항_종합.xlsx"
stamp = datetime.date.today().strftime("%Y%m%d")
for d in (REV, ORIG):
shutil.copy2(d / NAME, d / ("4개교_공통사항_종합_백업_%s_옥성갈고리C15C17.xlsx" % stamp))
wb = openpyxl.load_workbook(REV / NAME); ws, sh = wb["수정 내역"], wb["형상 일람(모델)"]
if any(r[0].value == "R-25" for r in ws.iter_rows(min_row=4)):
sys.exit("이미 있음")
def append_like(sheet, values, like_row):
r = sheet.max_row + 1
for j, v in enumerate(values, 1):
c = sheet.cell(row=r, column=j, value=v); s = sheet.cell(row=like_row, column=j)
c.font = copy.copy(s.font); c.fill = copy.copy(s.fill); c.border = copy.copy(s.border); c.alignment = copy.copy(s.alignment); c.number_format = s.number_format
sheet.auto_filter.ref = "A3:%s%d" % (openpyxl.utils.get_column_letter(sheet.max_column), r)
return r
r = append_like(ws, ["R-25", "옥성교", "코핑 타이 C15·C17 — 도면 양끝 갈고리 반영 (C17 은 j550 겹침 2조각)",
"C15 24본, C17 24본 (P1-CP)", "모델: 양끝이 갈고리 없는 직선. 도면: 양끝 갈고리 r80, 호 길이 188, 꼬리 140 (C17 은 j550 포함)",
"직선 양끝에 갈고리 추가(호 188=134.65°, 꼬리 140), 방향은 단면 중심 쪽(z 일정 평면). C17 은 가운데에서 550 겹치는 2조각. 길이 증가: C15 +656, C17 +1,206(656+550)",
48, "사용자 지시 2026-10-27: C15·C17 형상 수정(도면 맞춤), 이미지 캡처 엑셀 기재",
"옥성교P1_G5_수정9_20261027.3dm (수정8 기반)",
"재료표 L 역산: C15 7,632 = a평균 6,976 + 2×(188+140) 일치, C17 13,001 = 11,795 + 656 + 550 일치. 모델 직선 평균은 도면 a 보다 약 44 짧음(C17 모델 12,956 ↔ 표 13,001). 이미지: 수정후_캡처\옥성교_타이C15C17_갈고리_전후.png",
"갈고리 방향(단면 중심 쪽, 평면 z 일정)은 가정 — 도면 평면·단면에서 확인 필요. C17 j550 위치는 가운데로 가정. 겹침부 파이프는 같은 선상 중복"], 4)
ws.cell(row=r, column=1).fill = PatternFill("solid", fgColor="FFFFF2CC")
row = max(i.anchor._from.row + int(i.height / 20) for i in sh._images) + 6
sh.cell(row=row, column=1, value="옥성 C9·C11·C13 오각형 스터럽 c=630 겹침 — 전후 (R-25)").font = Font(bold=True, size=12)
im = XLImage(str(REV / "수정후_캡처" / "옥성교_타이C15C17_갈고리_전후.png")); w0, h0 = im.width, im.height
im.width, im.height = 1000, int(1000 * h0 / w0); sh.add_image(im, "A%d" % (row + 1))
wb.save(REV / NAME); shutil.copy2(REV / NAME, ORIG / NAME)
sha = lambda p: hashlib.sha256(Path(p).read_bytes()).hexdigest()
print("sha equal:", sha(REV / NAME) == sha(ORIG / NAME), sha(REV / NAME)[:16], len(sh._images))
@@ -0,0 +1,112 @@
"""갈고리 직선 b 보정(R-17)과 Ramp-A P3-1 콘크리트 돌출 오류(M-9)를 엑셀에 반영한다 (2026-10-26).
- 교량별 항목 합본 / 개별 항목: Ramp-A M-9 (P3-1 콘크리트 밖으로 튀어나감) 행
- 수정 내역 R-17, 수정 증거(마크별) 행, 미수정·보류 행, 수정 파일·해시(Ramp-A 수정5, 옥성 수정6 최신)
같은 R-17 이 이미 있으면 중단(이중 적용 방지).
"""
import copy
import datetime
import hashlib
import json
import sys
from pathlib import Path
import openpyxl
from openpyxl.styles import PatternFill
ROOT = Path(r"D:\★Pier 자료\프로그램\Pier_T")
REV = ROOT / "검토파일"
RES = ROOT / "Code" / "검토수정" / "결과"
XLSX = REV / "4개교_공통사항_종합.xlsx"
fx = json.loads((RES / "c1_hook_b_fix.json").read_text(encoding="utf-8"))
pr = json.loads((RES / "c1_protrude_check.json").read_text(encoding="utf-8"))
wb = openpyxl.load_workbook(XLSX)
ws = wb["수정 내역"]
if any(r[0].value == "R-17" for r in ws.iter_rows(min_row=4)):
sys.exit("R-17 이 이미 있음 - 중단")
GREEN = PatternFill("solid", fgColor="FFE2EFDA")
ORANGE = PatternFill("solid", fgColor="FFF8CBAD")
def append_like(sheet, values, like_row):
r = sheet.max_row + 1
for j, v in enumerate(values, 1):
c = sheet.cell(row=r, column=j, value=v)
s = sheet.cell(row=like_row, column=j)
c.font = copy.copy(s.font)
c.fill = copy.copy(s.fill)
c.border = copy.copy(s.border)
c.alignment = copy.copy(s.alignment)
c.number_format = s.number_format
sheet.auto_filter.ref = "A3:%s%d" % (openpyxl.utils.get_column_letter(sheet.max_column), r)
return r
b4, a4 = pr["before(수정2)"]["bars"], pr["after(수정5)"]["bars"]
p5, p3, p31 = fx["okseong"]["sample"]["P5"], fx["rampa"]["sample"]["P3"], fx["rampa"]["sample"]["P3-1"]
n_p5, n_p3, n_p31 = fx["okseong"]["stat"]["P5_done"], fx["rampa"]["stat"]["P3_done"], fx["rampa"]["stat"]["P3-1_done"]
CONTENT = ("Ramp-A교 P3-1(H16, 48본)이 기존 모델에서 콘크리트(기둥) 밖으로 튀어나가 있음 (사용자 지적 2026-10-26). "
"측정(콘크리트 솔리드 기준): 기존 모델 P3-1 중심선이 기둥 표면에 놓여 중심 피복 최소 %.1f mm (< 철근 반지름 8 mm → 파이프가 표면 밖으로 돌출), P3 는 최소 %.1f mm (경미)" %
(b4["P3-1"]["min_centre_cover_inside_mm"], b4["P3"]["min_centre_cover_inside_mm"]))
DIFF = ("기존: P3-1 다리가 기둥 표면 위(중심 피복 0.1). b 보정(R-17) 후 수정5: P3-1 %d본 중 %d본의 갈고리 일부가 콘크리트 밖 (최대 %.0f mm 길이) — 악화" %
(a4["P3-1"]["n"], a4["P3-1"]["bars_with_part_outside_concrete"], a4["P3-1"]["max_outside_length_mm"]))
STATUS = ("미해결: 도면 치수(a 200, b 2,137, r135 c165 d150)대로 만들면 다리가 기둥 표면에 걸리고 갈고리가 밖으로 나감. "
"기둥 단면(콘크리트 외곽)과 P3-1 배치 위치·방향을 도면에서 다시 확인해 위치를 조정해야 함 — 설계자 확인")
# 합본 / 개별
wg = wb["교량별 항목 합본"]
like = next(r[0].row for r in wg.iter_rows(min_row=4) if r[8].value == "도면↔모델")
append_like(wg, ["Ramp-A교", "M-9", "P3-1", CONTENT, "콘크리트 솔리드 ↔ 철근 중심선 (샘플 15 mm 간격)", DIFF,
"도면 상세 P3-1: r135 a200 b2,137 c165 d150 (갈고리 직선). 배치 높이·방향은 도면에 직접 표기 없음 [추론]", STATUS, "도면↔모델 (피복·돌출)", "개별"], like)
wi = wb["개별 항목"]
like_i = next(r[0].row for r in wi.iter_rows(min_row=4) if r[5].value == "도면↔모델")
append_like(wi, ["Ramp-A교", "M-9", "P3-1", CONTENT, DIFF, "도면↔모델 (피복·돌출)", STATUS], like_i)
# 수정 내역
r = append_like(ws, ["R-17", "옥성·Ramp-A", "갈고리 직선 b 보정 (R-15 후속)", "옥성 P5, Ramp-A P3·P3-1",
"b = 꺾임 꼭짓점까지 잰 값: P5 %.1f / P3 %.1f / P3-1 %.1f (도면 b 보다 57.9 짧음 = R24×tan67.5°)" % (p5["b_before"], p3["b_before"], p31["b_before"]),
"b = 다리선에서 호 시작점까지 (도면): P5 2,341 / P3 1,832 / P3-1 2,137. 중심선 길이 P5 %.1f / P3 %.1f / P3-1 %.1f" % (p5["len_after"], p3["len_after"], p31["len_after"]),
n_p5 + n_p3 + n_p31,
"사용자 질문 2026-10-26('P3, P3-1 형상 제대로 만들었니?') 점검에서 발견: 도면 b 는 다리선~호 시작점. 호 뒤쪽(호+끝)을 직선 방향으로 57.9 평행 이동",
"옥성교P1_G5_수정6_20261026.3dm / ramp-A G5_수정5_20261026.3dm",
"수정 후 재측정: a·b 가 도면과 일치(P5 160/2,341, P3 200/1,832, P3-1 200/2,137). 객체 수 동일",
"P3-1 은 b 를 늘리자 갈고리가 콘크리트 밖으로 나감 (M-9, 미해결). P3·P5 는 콘크리트 안"], 4)
ws.cell(row=r, column=1).fill = GREEN
ev = wb["수정 증거(마크별)"]
for m, br, s, n in (("P5", "옥성교", p5, n_p5), ("P3", "Ramp-A교", p3, n_p3), ("P3-1", "Ramp-A교", p31, n_p31)):
append_like(ev, [br, m, "H16", "갈고리 직선 b 보정", n, "b %.1f / 길이 %.1f" % (s["b_before"], s["len_before"]), "b %.1f / 길이 %.1f" % (s["b_after"], s["len_after"]),
round((s["len_after"] - s["len_before"]) * n, 1), "도면 b = 다리선~호 시작점. 호·끝을 +57.9 평행 이동"], 4)
append_like(ev, ["Ramp-A교", "P3-1", "H16", "콘크리트 돌출 측정(기둥 솔리드)", 48, "중심 피복 최소 %.1f mm, 콘크리트 밖 0본" % b4["P3-1"]["min_centre_cover_inside_mm"],
"수정5: 밖 %d본, 최대 %.0f mm" % (a4["P3-1"]["bars_with_part_outside_concrete"], a4["P3-1"]["max_outside_length_mm"]), None,
"c1_protrude_check.py (콘크리트 솔리드 IsPointInside / ClosestPoint). 기존 = ramp-A G5_검토완료.3dm"], 4)
hold = wb["미수정·보류"]
append_like(hold, ["Ramp-A교", "P3-1 (H16)", "48본", "기존 모델에서 콘크리트 밖으로 튀어나감 (중심 피복 0.1 mm), 수정5 에서는 26본 갈고리가 밖으로 나감",
"도면 치수(b 2,137, 갈고리)대로면 기둥 표면에 걸림. 배치 위치·방향 재확인 필요. 'M-9', '수정 내역' R-17",
"도면에서 P3-1 배치와 기둥 단면 확인(설계자)", "M-9"], 4)
fs = wb["수정 파일·해시"]
def sha(p):
h = hashlib.sha256()
with open(p, "rb") as f:
for blk in iter(lambda: f.read(1 << 20), b""):
h.update(blk)
return h.hexdigest()
for row in fs.iter_rows(min_row=4):
n = str(row[1].value).split("/")[-1]
if n in ("ramp-A G5_수정3_20261026.3dm", "ramp-A G5_수정4_20261026.3dm", "옥성교P1_G5_수정5_20261026.3dm") and row[3].value == "최신":
row[3].value = "중간본"
row[3].fill = PatternFill(fill_type=None)
for b, rel, what in (("Ramp-A교", "Ramp-A교P1/ramp-A G5_수정5_20261026.3dm", "P3·P3-1 b 보정 포함 (P3-1 은 콘크리트 돌출 미해결) — 전체 수정 포함"),
("옥성교", "검토_옥성교P1/옥성교P1_G5_수정6_20261026.3dm", "P5 b 보정 포함 — 전체 수정 포함(전단철근 수정3 제외)")):
p = REV / rel
st = p.stat()
rr = append_like(fs, [b, "검토파일/" + rel, what, "최신", round(st.st_size / 1e6, 1),
datetime.datetime.fromtimestamp(st.st_mtime).strftime("%Y-%m-%d %H:%M"), sha(p)], 4)
fs.cell(row=rr, column=4).fill = GREEN
wb.save(XLSX)
print("saved")
@@ -0,0 +1,69 @@
"""옥성교 J 겹침(기초 B1~B8·B11·B12, 코핑 C1~C6, 수정7 2026-10-27)을 엑셀에 반영. 백업(양쪽) → Pier_T → 원본 복사 → SHA 확인."""
import copy, datetime, hashlib, json, shutil, sys
from pathlib import Path
import openpyxl
from openpyxl.drawing.image import Image as XLImage
from openpyxl.styles import Alignment, PatternFill
ROOT = Path(r"D:\★Pier 자료\프로그램\Pier_T"); REV = ROOT / "검토파일"; ORIG = Path(r"D:\★Pier 자료\심수석님 검토 파일"); NAME = "4개교_공통사항_종합.xlsx"
res = json.load(open(r"C:\Users\User\AppData\Local\PierApp\jobs\c1_work\c1_lap_okseong.json", encoding="utf-8-sig"))
J = {"B1": 1530, "B3": 1530, "B5": 1530, "B7": 1530, "B2": 1070, "B4": 1070, "B6": 1070, "B8": 1070, "B11": 560, "B12": 560, "C1": 1510, "C2": 1510, "C3": 1510, "C4": 1510, "C5": 1510, "C6": 1510}
stamp = datetime.date.today().strftime("%Y%m%d")
for d in (REV, ORIG):
shutil.copy2(d / NAME, d / ("4개교_공통사항_종합_백업_%s_옥성J겹침.xlsx" % stamp))
wb = openpyxl.load_workbook(REV / NAME)
ws = wb["수정 내역"]
if any(r[0].value == "R-22" for r in ws.iter_rows(min_row=4)):
sys.exit("R-22 이미 있음")
GREEN = PatternFill("solid", fgColor="FFE2EFDA")
def append_like(sheet, values, like_row):
r = sheet.max_row + 1
for j, v in enumerate(values, 1):
c = sheet.cell(row=r, column=j, value=v); s = sheet.cell(row=like_row, column=j)
c.font = copy.copy(s.font); c.fill = copy.copy(s.fill); c.border = copy.copy(s.border); c.alignment = copy.copy(s.alignment); c.number_format = s.number_format
sheet.auto_filter.ref = "A3:%s%d" % (openpyxl.utils.get_column_letter(sheet.max_column), r)
return r
nb = sum(v for k, v in res["stat"].items() if k.startswith("B")); nc = sum(v for k, v in res["stat"].items() if k.startswith("C"))
r = append_like(ws, ["R-22", "옥성교", "J(겹침이음) 반영 — 기초 B1~B8·B11·B12 + 코핑 C1~C6",
"기초 B1~B8(j 1,530/1,070), B11·B12(j 560), 코핑 C1~C6(j 1,510)",
"도면 철근 상세에 j 가 있으나 모델은 1본 연속 형상(재료표 L 에만 반영)",
"긴 직선 구간 중앙에서 2조각이 j 만큼 겹침(산외교 기초·코핑과 같은 방식). 기초 %d본, 코핑 %d본" % (nb, nc),
nb + nc, "사용자 요청 2026-10-27: 나머지 교량도 코핑부·기초부 J 처럼 수정. 대조표의 j 값(B1 1.530 등)을 사용, 재료표 L = a+2b+j 로 확인(B1 9,400+1,800+1,530 = 12,730)",
"옥성교P1_G5_수정7_20261027.3dm", "객체 수 %d → %d. 조각 길이 합 = 기존 + j (B1 11,144 → 12,674 등), 파이프 부피 오차 0.5%% 이내, Rhino 캡처 확인" % (res["objects_before"], res["objects_after"]),
"미작업: 코핑 C7(j1,050 경사형), 루프형 C14·C16(j550×4)·B10(j560×6) — 겹침 위치·조각 구성을 도면 그림으로 확인 필요, C15·C17(모델 직선 vs 도면 갈고리, 형상 불일치 먼저). 운곡교는 재료표에 J 열 값이 없어 대상 없음, Ramp-A 는 C14(j290)만 있고 루프형이라 보류"], 4)
ws.cell(row=r, column=1).fill = GREEN
ev = wb["수정 증거(마크별)"]
for m, i in res["info"].items():
append_like(ev, ["옥성교", m, "-", "J 겹침 2조각(j %d)" % J[m], i["bars"], "1본 연속, 길이 평균 %.1f" % i["avg_len_old"], "2조각 j 겹침, 조각 길이 합 평균 %.1f" % i["avg_len_new_sum_of_pieces"],
round(i["avg_len_new_sum_of_pieces"] - i["avg_len_old"], 1), "R-22. 파일 옥성교P1_G5_수정7_20261027.3dm"], 4)
fs = wb["수정 파일·해시"]
sha = lambda p: hashlib.sha256(Path(p).read_bytes()).hexdigest()
for row in fs.iter_rows(min_row=4):
if str(row[1].value).endswith("옥성교P1_G5_수정6_20261026.3dm") and row[3].value == "최신":
row[3].value = "중간본"; row[3].fill = PatternFill(fill_type=None)
p = REV / "검토_옥성교P1" / "옥성교P1_G5_수정7_20261027.3dm"; s = p.stat()
rr = append_like(fs, ["옥성교", "검토파일/검토_옥성교P1/옥성교P1_G5_수정7_20261027.3dm", "기초 B1~B8·B11·B12, 코핑 C1~C6 J 겹침 — 전체 수정 포함", "최신", round(s.st_size / 1e6, 1),
datetime.datetime.fromtimestamp(s.st_mtime).strftime("%Y-%m-%d %H:%M"), sha(p)], 4)
fs.cell(row=rr, column=4).fill = GREEN
hold = wb["미수정·보류"]
append_like(hold, ["옥성교", "J 겹침 미작업: C7, C14·C16, B10, C15·C17", "-", "코핑 C7(경사형 j1,050), 루프형 C14·C16(j550×4)·B10(j560×6), C15·C17(모델 직선·도면 갈고리 불일치)",
"겹침 위치·조각 구성을 도면 그림으로 확인해야 함. 'R-22'", "도면 그림 확인 후 진행"], 4)
append_like(hold, ["운곡교·Ramp-A교", "J 겹침 대상 확인", "-", "운곡교: 재료표 J 열에 값 없음(대상 없음). Ramp-A: 대조표에 j 는 C14(j290)만 있고 루프형", "루프형 겹침 구성은 도면 그림 확인 필요. 'R-22'", "Ramp-A C14 도면 확인"], 4)
wd = wb["공통 문제 상세(이미지)"]
nr = wd.max_row + 1; like = nr - 1
vals = {1: "C-3", 2: "[개별] 옥성교 J(겹침이음) 반영 — 기초 B1~B8·B11·B12 + 코핑 C1~C6 (수정7)",
7: "도면 철근 상세에 j 가 있으나(B1 1,530, B2 1,070, B11·B12 560, C1~C6 1,510) 모델은 1본 연속 형상",
8: "긴 직선 구간 중앙에서 2조각 j 겹침 (기초 %d본, 코핑 %d본)" % (nb, nc),
9: "수정 완료(2026-10-27) 'R-22'. 루프형·경사형·C15·C17 은 도면 그림 확인 후 진행"}
for col, v in vals.items():
c = wd.cell(row=nr, column=col, value=v); s2 = wd.cell(row=like, column=col)
c.font = copy.copy(s2.font); c.fill = copy.copy(s2.fill); c.border = copy.copy(s2.border); c.alignment = Alignment(wrap_text=True, vertical="top")
wd.cell(row=nr, column=9).fill = copy.copy(GREEN)
wd.row_dimensions[nr].height = 560
im = XLImage(str(REV / "수정후_캡처" / "옥성교_J겹침_전후.png")); w0, h0 = im.width, im.height
im.width, im.height = 1000, int(1000 * h0 / w0); wd.add_image(im, "F%d" % nr)
wb.save(REV / NAME); shutil.copy2(REV / NAME, ORIG / NAME)
print("sha equal:", sha(REV / NAME) == sha(ORIG / NAME), sha(REV / NAME)[:16], "images:", len(openpyxl.load_workbook(REV / NAME)["공통 문제 상세(이미지)"]._images), "row", nr)
@@ -0,0 +1,96 @@
"""산외교 J 겹침(코핑 전단철근 시험 수정4 + 기초 B2·B5·B8 수정5, 2026-10-27)을 엑셀에 반영한다.
백업(양쪽 폴더) → Pier_T 사본 수정 → 원본 폴더로 복사 → SHA-256 확인. R-19 가 이미 있으면 중단."""
import copy, datetime, hashlib, json, shutil, sys
from pathlib import Path
import openpyxl
from openpyxl.drawing.image import Image as XLImage
from openpyxl.styles import Alignment, PatternFill
ROOT = Path(r"D:\★Pier 자료\프로그램\Pier_T")
REV = ROOT / "검토파일"
ORIG = Path(r"D:\★Pier 자료\심수석님 검토 파일")
NAME = "4개교_공통사항_종합.xlsx"
W = Path(r"C:\Users\User\AppData\Local\PierApp\jobs\c1_work")
cop = json.loads((W / "c1_lap_sanoe.json").read_text(encoding="utf-8"))
ft = json.loads((W / "c1_lap_sanoe_footing.json").read_text(encoding="utf-8"))
stamp = datetime.date.today().strftime("%Y%m%d")
for d in (REV, ORIG):
shutil.copy2(d / NAME, d / ("4개교_공통사항_종합_백업_%s_산외J겹침.xlsx" % stamp))
wb = openpyxl.load_workbook(REV / NAME)
ws = wb["수정 내역"]
if any(r[0].value == "R-19" for r in ws.iter_rows(min_row=4)):
sys.exit("R-19 이미 있음")
GREEN = PatternFill("solid", fgColor="FFE2EFDA")
def append_like(sheet, values, like_row):
r = sheet.max_row + 1
for j, v in enumerate(values, 1):
c = sheet.cell(row=r, column=j, value=v)
s = sheet.cell(row=like_row, column=j)
c.font = copy.copy(s.font); c.fill = copy.copy(s.fill); c.border = copy.copy(s.border); c.alignment = copy.copy(s.alignment); c.number_format = s.number_format
sheet.auto_filter.ref = "A3:%s%d" % (openpyxl.utils.get_column_letter(sheet.max_column), r)
return r
cs, fs_ = cop["stat"], ft["stat"]
ncop = sum(cs.values()); nft = sum(fs_.values())
r = append_like(ws, ["R-19", "산외교", "J(겹침이음) 반영 — 코핑 전단철근(시험) + 기초 B2·B5·B8",
"코핑 C7·C8·C9·C10·C12·C13 / 기초 B2·B5(IV, J=1,000), B8(V, J=570)",
"J 표기 없이 1본 연속 형상(ㅁ·U·ㄷ 한 줄)",
"재료표 J 를 반영해 2조각으로 나누고 J 만큼 같은 선에서 겹침 (코핑 %d본 + 기초 %d본, 조각 중심선 길이 합 = 기존 + J(IV·VIII) / +2J(II·V))" % (ncop, nft),
ncop + nft,
"대호지교 코드의 겹침 방식(II 뚜껑+바닥, III/XII/V 좌·우 ㄷ, VIII/IV L 두 개 + J 겹침). 사용자 요청 2026-10-27: 기초도 코핑처럼 수정",
"산외교P1 G5_수정4_20261026.3dm (코핑), 산외교P1 G5_수정5_20261027.3dm (코핑+기초, 최신)",
"객체 수 2004 → 2316 → 2454 (기초 B2 31·B5 31·B8 7본 → 조각 추가). 기초 평균 조각 합: B2 11757→12757, B5 11713→12713, B8 29339→30479. 파이프 부피 오차 0.5%% 이내, Rhino 캡처로 겹침 위치 확인",
"재료표 L(B8 31,581 등)은 III/XII/V 에서 2A+2B+4J 인데 모델 조각은 +2J 만 반영(도면 그림도 겹침 2곳) → 설계자 확인. 코핑 기둥(P2) 후프 J 380 및 다른 3개 교량은 미작업"], 4)
ws.cell(row=r, column=1).fill = GREEN
ev = wb["수정 증거(마크별)"]
for m, v in (("B2", "IV"), ("B5", "IV"), ("B8", "V")):
i = ft["info"][m]
append_like(ev, ["산외교", m, "-", "J 겹침 2조각(기초 %s)" % v, i["bars"], "1본 연속, 길이 평균 %.1f" % i["avg_len_old"], "2조각 J 겹침, 조각 길이 합 평균 %.1f" % i["avg_len_new_sum_of_pieces"],
round(i["avg_len_new_sum_of_pieces"] - i["avg_len_old"], 1), "R-19. 파일 산외교P1 G5_수정5_20261027.3dm"], 4)
for m, i in cop["info"].items():
append_like(ev, ["산외교", m, "-", "J 겹침 2조각(코핑 전단)", i["bars"], "1본 연속, 길이 평균 %.1f" % i["avg_len_old"], "2조각 J 겹침, 조각 길이 합 평균 %.1f" % i["avg_len_new_sum_of_pieces"],
round(i["avg_len_new_sum_of_pieces"] - i["avg_len_old"], 1), "R-19. 파일 산외교P1 G5_수정4_20261026.3dm"], 4)
fs = wb["수정 파일·해시"]
def sha(p):
h = hashlib.sha256()
with open(p, "rb") as f:
for b in iter(lambda: f.read(1 << 20), b""):
h.update(b)
return h.hexdigest()
for row in fs.iter_rows(min_row=4):
if str(row[1].value).endswith("산외교P1 G5_수정2_20261026.3dm") and row[3].value == "최신":
row[3].value = "승인본(J 겹침 전)"; row[3].fill = PatternFill(fill_type=None)
for nm, note, st in (("산외교P1 G5_수정4_20261026.3dm", "코핑 전단철근 J 겹침(시험)", "중간본"), ("산외교P1 G5_수정5_20261027.3dm", "코핑 + 기초 B2·B5·B8 J 겹침 — 전체 수정 포함", "최신")):
p = REV / "검토_산외교P1" / nm
s = p.stat()
rr = append_like(fs, ["산외교", "검토파일/검토_산외교P1/" + nm, note, st, round(s.st_size / 1e6, 1), datetime.datetime.fromtimestamp(s.st_mtime).strftime("%Y-%m-%d %H:%M"), sha(p)], 4)
if st == "최신":
fs.cell(row=rr, column=4).fill = GREEN
wd = wb["공통 문제 상세(이미지)"]
nr = wd.max_row + 1
like = nr - 1
vals = {1: "C-3", 2: "[개별] 산외교 J(겹침이음) 반영 — 코핑 전단철근 + 기초 B2·B5·B8 (수정4·5)",
7: "재료표 J(B2·B5 형상 IV J=1,000, B8 형상 V J=570)가 모델에 없고 1본 연속 형상이었음",
8: "대호지교 방식: IV → L 두 개를 하부 직선 중앙에서 J 만큼 겹침, V → 좌·우 ㄷ 두 개를 위·아래 변 중앙에서 겹침",
9: "수정 완료(2026-10-27) 'R-19'. 기초 B2 %d·B5 %d·B8 %d본, 코핑 %d본. 재료표 L 의 4J(III/XII/V)와 모델 2J 차이는 설계자 확인" % (fs_["B2_done"], fs_["B5_done"], fs_["B8_done"], ncop)}
for col, v in vals.items():
c = wd.cell(row=nr, column=col, value=v)
s = wd.cell(row=like, column=col)
c.font = copy.copy(s.font); c.fill = copy.copy(s.fill); c.border = copy.copy(s.border)
c.alignment = Alignment(wrap_text=True, vertical="top")
wd.cell(row=nr, column=9).fill = copy.copy(GREEN)
wd.row_dimensions[nr].height = 360
im = XLImage(str(REV / "수정후_캡처" / "산외교_기초J겹침_전후.png"))
w0, h0 = im.width, im.height
im.width, im.height = 1000, int(1000 * h0 / w0)
wd.add_image(im, "F%d" % nr)
wb.save(REV / NAME)
shutil.copy2(REV / NAME, ORIG / NAME)
print("sha equal:", sha(REV / NAME) == sha(ORIG / NAME), sha(REV / NAME)[:16], "images:", len(openpyxl.load_workbook(REV / NAME)["공통 문제 상세(이미지)"]._images), "row", nr)
@@ -0,0 +1,40 @@
"""옥성교 도면↔모델 마크별 대조 이미지를 '형상 일람(모델)' 시트 아래에 추가하고 '수정 내역' R-23(점검, 수정 없음) 기록. 백업(양쪽) → Pier_T → 원본 복사 → SHA 확인."""
import copy, datetime, hashlib, shutil, sys
from pathlib import Path
import openpyxl
from openpyxl.drawing.image import Image as XLImage
from openpyxl.styles import Font, PatternFill
ROOT = Path(r"D:\★Pier 자료\프로그램\Pier_T"); REV = ROOT / "검토파일"; ORIG = Path(r"D:\★Pier 자료\심수석님 검토 파일"); NAME = "4개교_공통사항_종합.xlsx"
CAP = REV / "수정후_캡처"
stamp = datetime.date.today().strftime("%Y%m%d")
for d in (REV, ORIG):
shutil.copy2(d / NAME, d / ("4개교_공통사항_종합_백업_%s_도면대조옥성.xlsx" % stamp))
wb = openpyxl.load_workbook(REV / NAME)
ws, sh = wb["수정 내역"], wb["형상 일람(모델)"]
if any(r[0].value == "R-23" for r in ws.iter_rows(min_row=4)):
sys.exit("이미 있음")
YEL = PatternFill("solid", fgColor="FFFFF2CC")
def append_like(sheet, values, like_row):
r = sheet.max_row + 1
for j, v in enumerate(values, 1):
c = sheet.cell(row=r, column=j, value=v); s = sheet.cell(row=like_row, column=j)
c.font = copy.copy(s.font); c.fill = copy.copy(s.fill); c.border = copy.copy(s.border); c.alignment = copy.copy(s.alignment); c.number_format = s.number_format
sheet.auto_filter.ref = "A3:%s%d" % (openpyxl.utils.get_column_letter(sheet.max_column), r)
return r
r = append_like(ws, ["R-23", "옥성교", "도면 철근상세 그림 ↔ 모델 형상 마크별 대조 (코핑 C1~C20·S1~S8, 기초 B1~B12)",
"옥성교 P1 코핑·기초 전 마크(이미지 2장)", "도면 그림과 모델 형상을 한 장에서 비교한 자료가 없었음",
"도면 그림(왼쪽)·모델 형상(오른쪽)·표 L/모델 L 을 마크별로 나란히 작성. 수정은 하지 않음 (시트 '형상 일람(모델)' 하단)",
0, "사용자 요청 2026-10-27: 겹침 보류 항목은 두고 도면 형상 대조 이미지 작성",
"옥성교P1_G5_수정7_20261027.3dm (형상은 수정6 시점 추출, J 겹침 전후 형상 동일)",
"일치: C1~C6, C8·C10·C12, C7, C18~C20, S1~S8, B1~B8·B11·B12. 확인: C9·C11·C13(오각형), B9, B10. 도면 그림 없음: C14·C16(j550×4 루프)",
"불일치: C15·C17 — 도면은 양끝 갈고리(r80, b188, c140; C17 은 j550 포함) / 모델은 직선. 형상 보정 필요(도면 확인 후 진행). 이미지의 모델 L 은 J 겹침 이전 측정값"], 4)
ws.cell(row=r, column=1).fill = YEL
row = max(i.anchor._from.row + int(i.height / 20) for i in sh._images) + 6
for p in (CAP / "도면대조_옥성_코핑.png", CAP / "도면대조_옥성_기초.png"):
sh.cell(row=row, column=1, value="옥성 " + p.stem.split("_")[-1] + " — 도면 ↔ 모델 대조").font = Font(bold=True, size=12)
im = XLImage(str(p)); w0, h0 = im.width, im.height
im.width, im.height = 1250, int(1250 * h0 / w0)
sh.add_image(im, "A%d" % (row + 1)); row += int(im.height / 20) + 4
wb.save(REV / NAME); shutil.copy2(REV / NAME, ORIG / NAME)
sha = lambda p: hashlib.sha256(Path(p).read_bytes()).hexdigest()
print("sha equal:", sha(REV / NAME) == sha(ORIG / NAME), sha(REV / NAME)[:16], "sheet images:", len(sh._images))
@@ -0,0 +1,54 @@
"""Ramp-A P3-1 M-9 에 '도면 r 과 c 불일치'를 추가하고 갈고리 치수 확인 이미지를 '공통 문제 상세(이미지)' 에 넣는다 (2026-10-26).
도면 P3-1: r135, c165(호 길이), d150. r135 의 135° 호는 318 이어야 하는데 c 는 165 → c÷r = 70° (비표준). c 165 는 r70 의 135° 호(164.9)와 일치.
이미 추가되어 있으면(M-9 내용에 'r135 의 135°' 포함) 중단.
"""
import sys
from pathlib import Path
import copy
import openpyxl
from openpyxl.drawing.image import Image as XLImage
from openpyxl.styles import Alignment
ROOT = Path(r"D:\★Pier 자료\프로그램\Pier_T")
XLSX = ROOT / "검토파일" / "4개교_공통사항_종합.xlsx"
IMG = ROOT / "검토파일" / "수정후_캡처"
ADD = (" ※ 도면 r 과 c 가 서로 맞지 않음: r135 의 135° 호는 318 이어야 하는데 c=165 (호 길이). r 로 각도를 구하면 70.03° 로 비표준이고, "
"c 165 는 r70 의 135° 호(164.9)와 일치함 [도면 r 오류 의심]. 도면 값(r135·c165·d150) 그대로 만들면 갈고리가 안쪽이 아니라 바깥(아래 오른쪽)으로 꺾여 말뚝 밖으로 나감")
wb = openpyxl.load_workbook(XLSX)
wg = wb["교량별 항목 합본"]
row = next(r for r in wg.iter_rows(min_row=4) if r[0].value == "Ramp-A교" and r[1].value == "M-9")
if "r135 의 135°" in str(row[3].value):
sys.exit("이미 추가됨 - 중단")
row[3].value = str(row[3].value) + ADD
row[7].value = str(row[7].value) + " (도면 r 이 70 이면 135° 갈고리로 말뚝 안에 들어옴 — 설계자 확인)"
wi = wb["개별 항목"]
for r in wi.iter_rows(min_row=4):
if r[0].value == "Ramp-A교" and r[1].value == "M-9":
r[3].value = str(r[3].value) + ADD
for r in wb["미수정·보류"].iter_rows(min_row=4):
if r[0].value == "Ramp-A교" and str(r[1].value).startswith("P3-1"):
r[4].value = str(r[4].value) + " 도면 r135 와 c165 불일치(c165 는 r70·135° 와 일치) — 설계자 확인"
wd = wb["공통 문제 상세(이미지)"]
nr = wd.max_row + 1
like = nr - 1
texts = {1: "M-9", 2: "[개별] Ramp-A교 P3-1 갈고리 — 도면 r135 와 c165 불일치, 도면 치수대로면 말뚝 밖으로 나감 (도면 오류 의심)",
7: "도면 r135 에 c165(호 길이)는 70° 호 → 갈고리가 바깥으로 꺾임. 135° 갈고리라면 r70 (c 164.9) 이 맞음",
8: "도면 r 값(135 ↔ 70) 설계자 확인. 확인 전에는 도면 값 그대로 두고 오류로 기록",
9: "[오류 기록] 모델은 도면 값(r135·c165·d150)대로 작성: 호 70.03°, 호 길이 165.0, 곧은 구간 150.0. 아래 말뚝 구간(반지름 1,175) 26본 중심이 말뚝 밖, 위 구간(반지름 1,250) 22본 표면 돌출. '미수정·보류', M-9"}
for col, v in texts.items():
c = wd.cell(row=nr, column=col, value=v)
s = wd.cell(row=like, column=col)
c.font = copy.copy(s.font); c.fill = copy.copy(s.fill); c.border = copy.copy(s.border)
c.alignment = Alignment(wrap_text=True, vertical="top")
for col in (3, 4, 5, 10, 11, 12):
wd.cell(row=nr, column=col, value="(해당 없음 — Ramp-A교 P3-1)" if col < 6 else "(해당 없음)")
wd.row_dimensions[nr].height = 420
for fname, anchor in (("RampA_P3-1_갈고리_치수확인.png", "F%d" % nr), ("RampA_P3_갈고리_치수확인.png", "M%d" % nr)):
im = XLImage(str(IMG / fname))
w0, h0 = im.width, im.height
im.width, im.height = 560, int(560 * h0 / w0)
wd.add_image(im, anchor)
wb.save(XLSX)
print("saved; row", nr)
@@ -0,0 +1,37 @@
"""옥성교 도면 내부 오류·정보 누락(D-11~D-13)을 '교량별 항목 합본'에 기록하고 '수정 내역' R-25 비고를 보강. 하루 1백업."""
import copy, hashlib, shutil, sys
from pathlib import Path
import openpyxl
from openpyxl.styles import PatternFill
from xlsx_backup_once import backup_once, NAME
ROOT = Path(r"D:\★Pier 자료\프로그램\Pier_T"); REV = ROOT / "검토파일"; ORIG = Path(r"D:\★Pier 자료\심수석님 검토 파일")
print("backup:", backup_once())
wb = openpyxl.load_workbook(REV / NAME); hb = wb["교량별 항목 합본"]; ws = wb["수정 내역"]
if any(r[1] == "D-11" for r in hb.iter_rows(min_row=4, values_only=True)):
sys.exit("이미 있음")
YEL = PatternFill("solid", fgColor="FFFFF2CC")
def append_like(sheet, values, like_row):
r = sheet.max_row + 1
for j, v in enumerate(values, 1):
c = sheet.cell(row=r, column=j, value=v); s = sheet.cell(row=like_row, column=j)
c.font = copy.copy(s.font); c.fill = copy.copy(s.fill); c.border = copy.copy(s.border); c.alignment = copy.copy(s.alignment); c.number_format = s.number_format
return r
rows = [
["옥성교", "D-11", "C15·C17", "갈고리(r80, 호 188, 꼬리 140)가 어느 평면·어느 방향으로 꺾이는지 도면에 표기 없음",
"도면 철근상세 그림 ↔ 도면 단면(A-A 등)·평면", "방향 미표기", "상세 그림은 형상만 있고 단면 A-A 에서는 수평철근이 점으로만 보임(갈고리 안 보임)",
"설계자 확인 필요. 현재 모델(수정9)은 단면 중심 쪽·z 일정 평면으로 가정", "도면↔도면 (정보 누락)", "개별 (옥성교)"],
["옥성교", "D-12", "B10", "표는 j=560×6(겹침 6곳, 표 L 41,152 = 4×9,448 + 6×560)인데 형식 그림에는 j 가 위·아래 2곳만 그려져 있고 위치 미표기",
"도면 철근상세 그림 ↔ 도면 재료표", "j 위치·구성 6곳 vs 그림 2곳", "겹침 6곳의 위치·조각 구성을 알 수 없음",
"설계자 확인 필요. 현재 모델은 겹침 없는 닫힌 링(보류)", "도면↔도면 (도면 내부 오류)", "개별 (옥성교)"],
["옥성교", "D-13", "C14·C16", "재료표에 j=550×4 루프형이 있으나 철근상세에 형상 그림이 없음",
"도면 재료표 ↔ 철근상세", "형상 그림 없음", "형상·겹침 위치 알 수 없음",
"설계자 확인 필요. 현재 모델은 겹침 없는 루프(보류)", "도면↔도면 (정보 누락)", "개별 (옥성교)"]]
for v in rows:
r = append_like(hb, v, hb.max_row); hb.cell(row=r, column=9).fill = YEL
for row in ws.iter_rows(min_row=4):
if row[0].value == "R-25":
c = row[10]; c.value = (str(c.value or "") + " / 2026-10-28 DXF(옥성교P1.dxf) 확인: 평면·단면에 갈고리 방향 표기 없음 → 합본 D-11 (도면 정보 누락)").strip()
hb.auto_filter.ref = "A3:%s%d" % (openpyxl.utils.get_column_letter(hb.max_column), hb.max_row)
wb.save(REV / NAME); shutil.copy2(REV / NAME, ORIG / NAME)
sha = lambda p: hashlib.sha256(Path(p).read_bytes()).hexdigest()
print("sha equal:", sha(REV / NAME) == sha(ORIG / NAME), sha(REV / NAME)[:16])
@@ -0,0 +1,136 @@
"""Ramp-A P3-1 갈고리를 P3 각도로 수정(수정6, 2026-10-27)한 내용을 엑셀에 반영한다.
- 도면 r135 각도가 이상해 보인다는 사용자 의견을 '도면 확인 필요'로 체크
- M-9 문구·구분·보류 행을 수정6 결과로 갱신, 수정 내역 R-18, 수정 증거, 파일·해시(수정6 최신)
- 공통 문제 상세(이미지) 24행 문구 갱신 + 25행(수정 전·후 이미지, 좌표) 추가
같은 R-18 이 이미 있으면 중단.
"""
import copy
import datetime
import hashlib
import json
import sys
from pathlib import Path
import openpyxl
from openpyxl.drawing.image import Image as XLImage
from openpyxl.styles import Alignment, PatternFill
ROOT = Path(r"D:\★Pier 자료\프로그램\Pier_T")
REV = ROOT / "검토파일"
RES = ROOT / "Code" / "검토수정" / "결과"
XLSX = REV / "4개교_공통사항_종합.xlsx"
a = json.loads((RES / "c1_p31_angle.json").read_text(encoding="utf-8"))
cv = json.loads((RES / "c1_radial_cover_s6.json").read_text(encoding="utf-8"))
c5, c6 = cv["수정5(r135 70도)"]["P3-1"], cv["수정6(P3 각도)"]["P3-1"]
co5 = json.loads((RES / "c1_hook_coords.json").read_text(encoding="utf-8"))["P1-RC-P3-1-L01X"]
co6 = json.loads((RES / "c1_hook_coords6.json").read_text(encoding="utf-8"))["P1-RC-P3-1-L01X"]
wb = openpyxl.load_workbook(XLSX)
ws = wb["수정 내역"]
if any(r[0].value == "R-18" for r in ws.iter_rows(min_row=4)):
sys.exit("R-18 이 이미 있음 - 중단")
GREEN = PatternFill("solid", fgColor="FFE2EFDA")
OLD_ADD = (" ※ 사용자 확인(2026-10-27): P3-1 은 r135 가 맞고 C 곡선(호 길이) 165, D 150 인 아래로 걸리는 갈고리 (호 70.03°) — r·c 불일치 아님. "
"모델(수정5)은 이 값 그대로. 이 형상은 갈고리가 아래·바깥으로 뻗어 말뚝 구간(반지름 1,175 / 1,250)의 밖으로 나감 → 도면 형상과 말뚝 단면(배치) 불일치, 설계자 확인")
NEW_ADD = (" ※ [도면 확인 필요] 도면 P3-1 의 r135 각도가 이상해 보임(사용자 의견 2026-10-27): P3 는 r60·c141 → 134.65° 갈고리인데 P3-1 은 r135·c165 → 70° 로 다른 모양이 되고 말뚝 밖으로 나감. "
"수정5 까지는 도면 값(r135)대로 작성했고, 수정6 에서 철근은 P3 각도(134.65°)를 따라 C 곡선 165·D 150 을 유지해 r %.2f 로 수정(48본, 말뚝 안: PL01 중심 피복 최소 %.1f / PL02 최소 %.1f mm). 도면 r135 가 맞는지는 설계자 확인" %
(a["sample"]["r"], c6["PL01"]["min_radial_centre_cover"], c6["PL02"]["min_radial_centre_cover"]))
REPL = [
(OLD_ADD, NEW_ADD),
("도면 오류로 보류: 도면 P3-1 치수는 반지름 1,250 구간에만 겨우 맞고 반지름 1,175 구간에서는 갈고리가 말뚝 밖으로 나감. 모델은 도면 치수대로 두고 오류로 기록. 구간별 치수는 설계자 확인",
"수정 완료(수정6, 2026-10-27): P3 각도(134.65°) 적용 → 말뚝 안. 도면 r135(70°) 자체는 설계자 확인 필요"),
(" (말뚝 단면·P3-1 배치 설계자 확인)", " (도면 r135 설계자 확인)"),
("도면 오류 (말뚝 돌출)", "도면 r 확인 필요 (수정6 으로 말뚝 안)"),
("[개별] Ramp-A교 P3-1 갈고리 — r135 · C 곡선 165 · D 150 (70° 아래로 걸림), 이 치수대로면 말뚝 밖으로 나감",
"[개별] Ramp-A교 P3-1 갈고리 — 도면 r135(70°) 각도가 이상해 보임, 철근은 P3 각도(134.65°)로 수정 (수정6)"),
("사용자 확인(2026-10-27): r135 가 맞고 C 곡선 길이 165, D 150. 호는 70.03° 로 아래로 걸림 — r·c 불일치 아님",
"사용자 의견(2026-10-27): 도면 r135 의 각도가 이상해 보임 — P3(r60, 134.65°)와 같은 갈고리인데 P3-1 은 70° 로 각도가 다름"),
("말뚝 단면(반지름 1,175 / 1,250 구간)과 P3-1 배치 위치 설계자 확인. 모델은 도면 값 그대로",
"도면 r 값 설계자 확인. 모델(수정6)은 P3 각도(134.65°) + C 165 + D 150 (r %.2f)" % a["sample"]["r"]),
("[오류 기록] 모델은 도면 값(r135·c165·d150)대로 작성: 호 70.03°, 호 길이 165.0, 곧은 구간 150.0. 아래 말뚝 구간(반지름 1,175) 26본 중심이 말뚝 밖, 위 구간(반지름 1,250) 22본 표면 돌출. '미수정·보류', M-9",
"수정 완료(2026-10-27): P3 각도(134.65°) 적용 → r %.2f · 호 길이 165.0 · 곧은 구간 150.0, 말뚝 안(PL01 최소 %.1f / PL02 최소 %.1f mm). 수정 전(도면 r135·70°)은 말뚝 밖(PL01 26본 중심 밖, PL02 22본 돌출). 파일 ramp-A G5_수정6_20261026.3dm, '수정 내역' R-18" %
(a["sample"]["r"], c6["PL01"]["min_radial_centre_cover"], c6["PL02"]["min_radial_centre_cover"])),
]
n = 0
for name in ("교량별 항목 합본", "개별 항목", "미수정·보류", "공통 문제 상세(이미지)", "수정 내역", "수정 증거(마크별)"):
for row in wb[name].iter_rows():
for c in row:
if isinstance(c.value, str):
v = c.value
for old, new in REPL:
if old in v:
v = v.replace(old, new)
if v != c.value:
c.value = v
n += 1
for r in wb["미수정·보류"].iter_rows(min_row=4):
if r[0].value == "Ramp-A교" and str(r[1].value).startswith("P3-1"):
r[3].value = "수정 완료(수정6): P3 각도로 다시 만들어 말뚝 안. (수정5 도면 r135·70° 는 PL01 26본 중심 밖, PL02 22본 표면 돌출)"
r[4].value = "사용자 의견: 도면 r135 의 각도(70°)가 이상해 보임 → 철근은 P3 각도(134.65°), C 165, D 150, r %.2f. 'M-9', 'R-18'" % a["sample"]["r"]
r[5].value = "도면 r135 설계자 확인"
def append_like(sheet, values, like_row):
r = sheet.max_row + 1
for j, v in enumerate(values, 1):
c = sheet.cell(row=r, column=j, value=v)
s = sheet.cell(row=like_row, column=j)
c.font = copy.copy(s.font); c.fill = copy.copy(s.fill); c.border = copy.copy(s.border); c.alignment = copy.copy(s.alignment); c.number_format = s.number_format
sheet.auto_filter.ref = "A3:%s%d" % (openpyxl.utils.get_column_letter(sheet.max_column), r)
return r
r = append_like(ws, ["R-18", "Ramp-A교", "P3-1 갈고리를 P3 각도로 수정", "P3-1 (H16)",
"도면 r135·c165·d150: 호 70.03°, 곧은 구간이 바깥으로 뻗음 / 말뚝 밖 (PL01 26본 중심 밖, PL02 22본 돌출)",
"P3 각도 134.65°, 호 길이 165.0, 곧은 구간 150.0, r %.2f (곧은 구간이 안쪽 아래로 되돌아옴) / 말뚝 안" % a["sample"]["r"], a["stat"]["done"],
"사용자 의견 2026-10-27: 도면 r135 의 각도가 이상해 보임 → 철근은 P3 각도를 따름. C 곡선 165, D 150 은 도면 값 유지, 반지름은 165 ÷ (141/60) = %.2f" % a["sample"]["r"],
"ramp-A G5_수정6_20261026.3dm",
"수정 후 재측정: r·호 각도·호 길이·곧은 구간·꼭짓점~호 시작(b 2,137) 확인, 말뚝 반경 기준 중심 피복 PL01 최소 %.1f / PL02 최소 %.1f mm(돌출 0본). 객체 수 %d → %d 동일" % (c6["PL01"]["min_radial_centre_cover"], c6["PL02"]["min_radial_centre_cover"], a["objects_before"], a["objects_after"]),
"도면 r135 의 각도 자체는 설계자 확인(체크). 증거: 공통 문제 상세(이미지) 25행 수정 전·후 Rhino 캡처·좌표"], 4)
ws.cell(row=r, column=1).fill = GREEN
ev = wb["수정 증거(마크별)"]
append_like(ev, ["Ramp-A교", "P3-1", "H16", "갈고리 각도를 P3 각도로", a["stat"]["done"], "r135 · 70.03° · c165 · d150 / 곧은 구간이 바깥", "r%.2f · 134.65° · c165 · d150 / 안쪽으로 되돌아옴" % a["sample"]["r"], 0.0,
"중심선 길이 불변(2,641.7). 좌표: 호 중심 (1068.5, 0, 33057.0) → (1068.5, 0, 33121.79), 곧은 구간 끝 (1246.61, 0, 32962.13) → (1013.05, 0, 32965.73)"], 4)
fs = wb["수정 파일·해시"]
def sha(p):
h = hashlib.sha256()
with open(p, "rb") as f:
for blk in iter(lambda: f.read(1 << 20), b""):
h.update(blk)
return h.hexdigest()
for row in fs.iter_rows(min_row=4):
if str(row[1].value).endswith("ramp-A G5_수정5_20261026.3dm") and row[3].value == "최신":
row[3].value = "중간본"
row[3].fill = PatternFill(fill_type=None)
p = REV / "Ramp-A교P1" / "ramp-A G5_수정6_20261026.3dm"
stt = p.stat()
rr = append_like(fs, ["Ramp-A교", "검토파일/Ramp-A교P1/ramp-A G5_수정6_20261026.3dm", "P3-1 갈고리 P3 각도 적용 — 전체 수정 포함", "최신", round(stt.st_size / 1e6, 1),
datetime.datetime.fromtimestamp(stt.st_mtime).strftime("%Y-%m-%d %H:%M"), sha(p)], 4)
fs.cell(row=rr, column=4).fill = GREEN
wd = wb["공통 문제 상세(이미지)"]
nr = wd.max_row + 1
like = nr - 1
pt = lambda co: "; ".join("%s 월드(%s) 2D(%s)" % (k.split("_")[0], ", ".join(str(x) for x in v["world"]), ", ".join(str(x) for x in v["2D(u,v)"])) for k, v in co["points"].items() if k.startswith(("⑤", "⑥", "⑦", "⑧")))
vals = {1: "M-9", 2: "[개별] Ramp-A교 P3-1 갈고리 수정 전·후 증거 (수정5 → 수정6)",
7: "수정 전(수정5) 철근 중심선 좌표: " + pt(co5) + " / d 방향(u,v) " + str(co5["d_direction(곧은구간 방향 단위벡터 u,v)"]),
8: "수정 후(수정6) 철근 중심선 좌표: " + pt(co6) + " / d 방향(u,v) " + str(co6["d_direction(곧은구간 방향 단위벡터 u,v)"]),
9: "수정 완료(2026-10-27): P3 각도(134.65°) 적용. 2D 좌표는 꼭짓점(다리선과 수평선 교점)을 원점, u = 수평선 방향, v = 위(+Z). 'R-18'"}
for col, v in vals.items():
c = wd.cell(row=nr, column=col, value=v)
s = wd.cell(row=like, column=col)
c.font = copy.copy(s.font); c.fill = copy.copy(s.fill); c.border = copy.copy(s.border)
c.alignment = Alignment(wrap_text=True, vertical="top")
wd.cell(row=nr, column=9).fill = copy.copy(GREEN)
wd.row_dimensions[nr].height = 460
im = XLImage(str(REV / "수정후_캡처" / "RampA_P3-1_갈고리_수정전후.png"))
w0, h0 = im.width, im.height
im.width, im.height = 900, int(900 * h0 / w0)
wd.add_image(im, "F%d" % nr)
wb.save(XLSX)
print("text cells updated:", n, "; new row", nr)
@@ -0,0 +1,129 @@
"""Ramp-A교 P3-2(ㄷ자철근 형상 오류) 수정을 엑셀에 반영한다 (2026-10-26).
- 교량별 항목 합본 / 개별 항목: Ramp-A M-8 (P3-2) 행 추가
- 수정 내역 R-16, 수정 증거(마크별) 행, 수정 파일·해시(수정4 최신, 수정3 중간본)
- 공통 문제 상세(이미지): 맨 아래 새 행에 수정 전(F열)·수정 후(M열) 이미지와 수정 내용(I열)
같은 R-16 이 이미 있으면 중단(이중 적용 방지).
"""
import copy
import datetime
import hashlib
import json
import sys
from pathlib import Path
import openpyxl
from openpyxl.drawing.image import Image as XLImage
from openpyxl.styles import Alignment, PatternFill
ROOT = Path(r"D:\★Pier 자료\프로그램\Pier_T")
REV = ROOT / "검토파일"
IMG = REV / "수정후_캡처"
XLSX = REV / "4개교_공통사항_종합.xlsx"
fx = json.loads((ROOT / "Code" / "검토수정" / "결과" / "c1_p32_fix.json").read_text(encoding="utf-8"))
smp = fx["samples"][0]
wb = openpyxl.load_workbook(XLSX)
ws = wb["수정 내역"]
if any(r[0].value == "R-16" for r in ws.iter_rows(min_row=4)):
sys.exit("R-16 이 이미 있음 - 중단")
GREEN = PatternFill("solid", fgColor="FFE2EFDA")
def clone(src, dst):
dst.font = copy.copy(src.font)
dst.fill = copy.copy(src.fill)
dst.border = copy.copy(src.border)
dst.alignment = copy.copy(src.alignment)
dst.number_format = src.number_format
def append_like(sheet, values, like_row):
r = sheet.max_row + 1
for j, v in enumerate(values, 1):
c = sheet.cell(row=r, column=j, value=v)
clone(sheet.cell(row=like_row, column=j), c)
sheet.auto_filter.ref = "A3:%s%d" % (openpyxl.utils.get_column_letter(sheet.max_column), r)
return r
CONTENT = ("Ramp-A교 P3-2(H16, 30본)는 도면(4) '철근망 최하단 저부철근 상세도'에서 바닥 수평 + 다리 수직 ㄷ자(다리 200 은 P1-2 에 용접)인데, "
"모델은 다리 위쪽 184 만 수직이고 그 아래 459 가 약 13.4° 안쪽으로 기울며 모서리가 R135 두 호(13.44° + 76.56°)로 이어진 깔때기 형상임")
DIFF = "다리 약 13.4° 기울어짐, 바닥 폭이 다리 위쪽 간격보다 좁음, 중심선 길이 3,276.3 (재료표 L 3,342)"
FIXED = ("수정 완료 (2026-10-26): 바닥 수평 + 다리 수직 ㄷ자로 다시 만듦 — 바닥 폭 2,050, 다리 높이 646 (W + 2h = 재료표 L 3,342), 모서리 R24 "
"(도면에 반지름 없어 KDS H16 최소 적용), 중심선 길이 3,321.4. 파일: ramp-A G5_수정4_20261026.3dm. '수정 내역' R-16")
# 합본
wg = wb["교량별 항목 합본"]
like = next(r[0].row for r in wg.iter_rows(min_row=4) if r[8].value == "도면↔모델")
r = append_like(wg, ["Ramp-A교", "M-8", "P3-2", CONTENT, "도면(4) 저부철근 상세도 ↔ 모델 형상", DIFF,
"바닥 수평 + 다리 수직 ㄷ자, 다리 200 이 P1-2 에 용접 표기 / 재료표 P3-2 H16 L 3.342 N 30",
FIXED, "도면↔모델 (수정 완료)", "개별"], like)
# 개별 항목
wi = wb["개별 항목"]
like_i = next(r[0].row for r in wi.iter_rows(min_row=4) if r[5].value == "도면↔모델")
append_like(wi, ["Ramp-A교", "M-8", "P3-2", CONTENT, DIFF, "도면↔모델 (수정 완료)", FIXED], like_i)
# 수정 내역 / 증거 / 파일
append_like(ws, ["R-16", "Ramp-A교", "ㄷ자철근 형상 오류 (P3-2)", "P3-2 (H16)",
"다리 위 184 수직 + 아래 459 약 13.4° 기울음 + 모서리 R135 두 호 / 바닥 폭 약 1,554+호 / 중심선 길이 %.1f" % smp["old_len"],
"바닥 수평 + 다리 수직 ㄷ자: 바닥 폭 %.0f, 다리 높이 %.0f, 모서리 R24 / 중심선 길이 %.1f" % (smp["W"], smp["h"], smp["new_len"]), fx["stat"]["done"],
"사용자 지적 2026-10-26: P3-2 는 그냥 ㄷ자 철근. 도면 저부철근 상세도 형상 + 재료표 L 3,342 (직선 치수 합 W + 2h), 모서리 R 은 도면에 없어 KDS H16 최소",
"ramp-A G5_수정4_20261026.3dm", "저장 직전 문서 확인: 30본 모두 재작성, 객체 수 %d → %d 동일, 파이프 부피 ±0.5%% 이내. 수정 전후 Rhino 캡처를 '공통 문제 상세(이미지)' 시트 맨 아래에 추가" % (fx["objects_before"], fx["objects_after"]),
"다리 위치·평면 각도는 모델 값 유지. 다리 높이는 L 에서 역산(646)이라 다리 200 용접 구간 포함 여부는 설계자 확인"], 4)
for row in ws.iter_rows(min_row=4):
if row[0].value == "R-16":
row[0].fill = GREEN
ev = wb["수정 증거(마크별)"]
append_like(ev, ["Ramp-A교", "P3-2", "H16", "ㄷ자 형상 재작성", fx["stat"]["done"],
"다리 일부 13.4° 기울음 / 길이 %.1f" % smp["old_len"], "ㄷ자 W %.0f · h %.0f · R24 / 길이 %.1f" % (smp["W"], smp["h"], smp["new_len"]),
round((smp["new_len"] - smp["old_len"]) * fx["stat"]["done"], 1), "도면 저부철근 상세도 + 재료표 L 3,342"], 4)
fs = wb["수정 파일·해시"]
def sha(p):
h = hashlib.sha256()
with open(p, "rb") as f:
for blk in iter(lambda: f.read(1 << 20), b""):
h.update(blk)
return h.hexdigest()
for row in fs.iter_rows(min_row=4):
if str(row[1].value).endswith("ramp-A G5_수정3_20261026.3dm") and row[3].value == "최신":
row[3].value = "중간본"
row[3].fill = PatternFill(fill_type=None)
p = REV / "Ramp-A교P1" / "ramp-A G5_수정4_20261026.3dm"
st = p.stat()
rr = append_like(fs, ["Ramp-A교", "검토파일/Ramp-A교P1/ramp-A G5_수정4_20261026.3dm", "P3-2 ㄷ자 재작성 — 전체 수정 포함", "최신", round(st.st_size / 1e6, 1),
datetime.datetime.fromtimestamp(st.st_mtime).strftime("%Y-%m-%d %H:%M"), sha(p)], 4)
fs.cell(row=rr, column=4).fill = GREEN
# 공통 문제 상세(이미지): 새 행
wd = wb["공통 문제 상세(이미지)"]
nr = wd.max_row + 1
wd.cell(row=nr, column=1, value="M-8")
wd.cell(row=nr, column=2, value="[개별] Ramp-A교 P3-2 ㄷ자철근 — 모델이 깔때기 형상 (도면은 바닥 수평 + 다리 수직 ㄷ자)")
wd.cell(row=nr, column=7, value="모델 생성 과정에서 다리 일부를 기울이고 모서리를 R135 두 호로 이은 것으로 추정 (코드 미확인). 도면 저부철근 상세도는 단순 ㄷ자")
wd.cell(row=nr, column=8, value="도면 형상(바닥 수평 + 다리 수직)과 재료표 L 3,342 로 다시 작도, 모서리 R 은 KDS H16 최소")
wd.cell(row=nr, column=9, value=FIXED)
for col in (1, 2, 7, 8, 9):
c = wd.cell(row=nr, column=col)
clone(wd.cell(row=nr - 3 if nr - 3 > 3 else 4, column=col), c)
c.alignment = Alignment(wrap_text=True, vertical="top")
wd.cell(row=nr, column=9).fill = copy.copy(GREEN)
wd.cell(row=nr, column=3, value="(해당 없음 — Ramp-A교 P3-2)")
wd.cell(row=nr, column=4, value="(해당 없음 — Ramp-A교 P3-2)")
wd.cell(row=nr, column=5, value="(해당 없음 — Ramp-A교 P3-2)")
wd.cell(row=nr, column=10, value="(해당 없음)")
wd.cell(row=nr, column=11, value="(해당 없음)")
wd.cell(row=nr, column=12, value="(해당 없음)")
wd.row_dimensions[nr].height = 360
for fname, anchor in (("RampA_P3-2_수정전.png", "F%d" % nr), ("RampA_P3-2_수정후.png", "M%d" % nr)):
im = XLImage(str(IMG / fname))
w0, h0 = im.width, im.height
im.width, im.height = 560, int(560 * h0 / w0)
wd.add_image(im, anchor)
wd.cell(row=nr, column=6).alignment = Alignment(wrap_text=True, vertical="top")
wb.save(XLSX)
print("saved; new row", nr)
@@ -0,0 +1,35 @@
"""옥성 C9·C11·C13 오각형 스터럽 c=630 겹침(수정8) 기록: '수정 내역' R-24 + 이미지(형상 일람 시트 하단). 백업(양쪽) → Pier_T → 원본 복사 → SHA 확인."""
import copy, datetime, hashlib, shutil, sys
from pathlib import Path
import openpyxl
from openpyxl.drawing.image import Image as XLImage
from openpyxl.styles import Font, PatternFill
ROOT = Path(r"D:\★Pier 자료\프로그램\Pier_T"); REV = ROOT / "검토파일"; ORIG = Path(r"D:\★Pier 자료\심수석님 검토 파일"); NAME = "4개교_공통사항_종합.xlsx"
stamp = datetime.date.today().strftime("%Y%m%d")
for d in (REV, ORIG):
shutil.copy2(d / NAME, d / ("4개교_공통사항_종합_백업_%s_옥성오각형겹침.xlsx" % stamp))
wb = openpyxl.load_workbook(REV / NAME); ws, sh = wb["수정 내역"], wb["형상 일람(모델)"]
if any(r[0].value == "R-24" for r in ws.iter_rows(min_row=4)):
sys.exit("이미 있음")
def append_like(sheet, values, like_row):
r = sheet.max_row + 1
for j, v in enumerate(values, 1):
c = sheet.cell(row=r, column=j, value=v); s = sheet.cell(row=like_row, column=j)
c.font = copy.copy(s.font); c.fill = copy.copy(s.fill); c.border = copy.copy(s.border); c.alignment = copy.copy(s.alignment); c.number_format = s.number_format
sheet.auto_filter.ref = "A3:%s%d" % (openpyxl.utils.get_column_letter(sheet.max_column), r)
return r
r = append_like(ws, ["R-24", "옥성교", "코핑 오각형 스터럽 C9·C11·C13 — 도면 c=630 겹침 반영 (2조각)",
"C9 78본, C11 54본, C13 80본 (P1-CP)", "모델: 끝이 맞닿은 닫힌 링(겹침 없음). 도면: 긴 세로 변 위쪽에서 아래로 c=630 만큼 두 끝이 겹침",
"겹침 구간(c=630)을 긴 세로 변 위쪽 끝에서 아래로 두고 철근을 2조각으로 분할. 조각 길이 합 = 기존 + 630 (C9 6205→6835, C11 7454→8084, C13 6139→6769 평균)",
212, "사용자 지시 2026-10-27: '전단철근 오각형인데 J 위치에서 잘라 만들기, 위치는 도면 상세·길이 산정으로'. c=630 겹침, c1=변하는 길이",
"옥성교P1_G5_수정8_20261027.3dm (수정7 기반)",
"도면 평균 치수 합(a+b+d+c1+c2)+630 ≈ 재료표 L (C9 7,489↔7,401, C13 6,741↔6,662). 이미지: 수정후_캡처\옥성교_오각형스터럽_C9C11C13_겹침_전후.png",
"C11 은 같은 산식으로 7,361↔7,992 로 안 맞음(재료표 값·d 범위 확인 필요). C15·C17 갈고리 형상 보정은 미반영. 파이프 겹침부는 같은 선상에 중복(기존 J 방식과 동일)"], 4)
ws.cell(row=r, column=1).fill = PatternFill("solid", fgColor="FFFFF2CC")
row = max(i.anchor._from.row + int(i.height / 20) for i in sh._images) + 6
sh.cell(row=row, column=1, value="옥성 C9·C11·C13 오각형 스터럽 c=630 겹침 — 전후 (R-24)").font = Font(bold=True, size=12)
im = XLImage(str(REV / "수정후_캡처" / "옥성교_오각형스터럽_C9C11C13_겹침_전후.png")); w0, h0 = im.width, im.height
im.width, im.height = 1000, int(1000 * h0 / w0); sh.add_image(im, "A%d" % (row + 1))
wb.save(REV / NAME); shutil.copy2(REV / NAME, ORIG / NAME)
sha = lambda p: hashlib.sha256(Path(p).read_bytes()).hexdigest()
print("sha equal:", sha(REV / NAME) == sha(ORIG / NAME), sha(REV / NAME)[:16], len(sh._images))
@@ -0,0 +1,36 @@
"""Ramp-A교 DXF 철근상세 ↔ 모델 마크별 대조 이미지 2장 기록(R-28). 하루 1백업."""
import copy, hashlib, shutil, sys
from pathlib import Path
import openpyxl
from openpyxl.drawing.image import Image as XLImage
from openpyxl.styles import Font, PatternFill
from xlsx_backup_once import backup_once, NAME
ROOT = Path(r"D:\★Pier 자료\프로그램\Pier_T"); REV = ROOT / "검토파일"; ORIG = Path(r"D:\★Pier 자료\심수석님 검토 파일"); CAP = REV / "수정후_캡처"
print("backup:", backup_once())
wb = openpyxl.load_workbook(REV / NAME); ws, sh = wb["수정 내역"], wb["형상 일람(모델)"]
if any(r[0].value == "R-28" for r in ws.iter_rows(min_row=4)):
sys.exit("이미 있음")
def append_like(sheet, values, like_row):
r = sheet.max_row + 1
for j, v in enumerate(values, 1):
c = sheet.cell(row=r, column=j, value=v); s = sheet.cell(row=like_row, column=j)
c.font = copy.copy(s.font); c.fill = copy.copy(s.fill); c.border = copy.copy(s.border); c.alignment = copy.copy(s.alignment); c.number_format = s.number_format
sheet.auto_filter.ref = "A3:%s%d" % (openpyxl.utils.get_column_letter(sheet.max_column), r)
return r
YEL = PatternFill("solid", fgColor="FFFFF2CC")
r = append_like(ws, ["R-28", "Ramp-A교", "도면(DXF 교각(3).dxf) 철근상세 그림 ↔ 모델 형상 마크별 대조 (코핑 C1~C16·S1~S4, 기둥 P1~P3, 말뚝 P1-1~P3-2)",
"Ramp-A교 P1 코핑·기둥·말뚝 전 마크(이미지 2장)", "철근상세 그림을 마크별로 모델과 한 장에서 비교한 자료가 없었음",
"DXF 철근상세 영역을 렌더(ezdxf)해 마크별 그림을 잘라 모델 형상 옆에 배치(시트 '형상 일람(모델)' 하단). 수정은 하지 않음",
0, "사용자 지시 2026-10-28: DXF 도면을 제1 자료로, 그림은 DXF 에서 잘라 넣기", "ramp-A G5_수정6_20261026.3dm",
"형상 불일치 없음: C1~C5 ㄷ(다리각 107°/103°), C6 soffit 호, C7·C9·C11 사각 링, C8·C10·C12 오각형, C13·C14 사각 링, C15·C16·S1·S2 ㄷ, S3·S4 직선, P1 직선(커플러), P2·P2-1 반원 후프, P3·P3-1 갈고리",
"P1-1·P1-2·P3-2 는 도면에 마크 전용 그림이 없어 같은 계열 그림으로 추정 표시. C14 도면에 j=290×1 이 그려져 있으나 모델 링에 겹침 없음(보류, 사용자 지시로 겹침은 당분간 그대로 둠)"], 4)
ws.cell(row=r, column=1).fill = YEL
row = max(i.anchor._from.row + int(i.height / 20) for i in sh._images) + 6
for part in ("코핑", "기둥말뚝"):
p = CAP / ("도면대조_RampA_%s.png" % part)
sh.cell(row=row, column=1, value="Ramp-A %s — DXF 철근상세 그림 ↔ 모델 대조" % part).font = Font(bold=True, size=12)
im = XLImage(str(p)); w0, h0 = im.width, im.height
im.width, im.height = 1250, int(1250 * h0 / w0); sh.add_image(im, "A%d" % (row + 1)); row += int(im.height / 20) + 4
wb.save(REV / NAME); shutil.copy2(REV / NAME, ORIG / NAME)
sha = lambda p: hashlib.sha256(Path(p).read_bytes()).hexdigest()
print("sha equal:", sha(REV / NAME) == sha(ORIG / NAME), sha(REV / NAME)[:16], len(sh._images))
@@ -0,0 +1,35 @@
"""산외교 도면↔모델 마크별 대조 이미지(코핑·기초·기둥)를 '형상 일람(모델)' 시트 하단에 추가, '수정 내역' R-26(점검, 수정 없음) 기록. 하루 1백업 → Pier_T → 원본 복사 → SHA 확인."""
import copy, hashlib, shutil, sys
from pathlib import Path
import openpyxl
from openpyxl.drawing.image import Image as XLImage
from openpyxl.styles import Font, PatternFill
from xlsx_backup_once import backup_once, NAME
ROOT = Path(r"D:\★Pier 자료\프로그램\Pier_T"); REV = ROOT / "검토파일"; ORIG = Path(r"D:\★Pier 자료\심수석님 검토 파일"); CAP = REV / "수정후_캡처"
print("backup:", backup_once())
wb = openpyxl.load_workbook(REV / NAME); ws, sh = wb["수정 내역"], wb["형상 일람(모델)"]
if any(r[0].value == "R-26" for r in ws.iter_rows(min_row=4)):
sys.exit("이미 있음")
def append_like(sheet, values, like_row):
r = sheet.max_row + 1
for j, v in enumerate(values, 1):
c = sheet.cell(row=r, column=j, value=v); s = sheet.cell(row=like_row, column=j)
c.font = copy.copy(s.font); c.fill = copy.copy(s.fill); c.border = copy.copy(s.border); c.alignment = copy.copy(s.alignment); c.number_format = s.number_format
sheet.auto_filter.ref = "A3:%s%d" % (openpyxl.utils.get_column_letter(sheet.max_column), r)
return r
r = append_like(ws, ["R-26", "산외교", "재료표 형식 ↔ 같은 강종 도면 형식 그림 ↔ 모델 형상 마크별 대조 (코핑·기초·기둥 전 마크)",
"산외교 P1 코핑 C1~C15·S1~S4, 기초 B1~B10, 기둥 P1~P5 (이미지 3장)", "형식 번호만으로 점검했고 도면 형식 그림과 모델을 한 장에서 비교한 자료가 없었음",
"SD400/SD500 상세 그림을 형식별로 잘라 모델 형상 옆에 배치(시트 '형상 일람(모델)' 하단). 수정은 하지 않음",
0, "사용자 요청 2026-10-27 '도면 형상 대조 이미지 4개교' 이어서 (2026-10-28)", "산외교P1 G5_수정5_20261027.3dm",
"형식 불일치 없음: SD500 형식 I(B1·B3·B4·B6)=직선, B7·C14·C15·S1~S4·P5(SD400 형식 I)=ㄷ, B9·B10(III)=ㄷ, C1~C4(IX)·C5~C6(IV)·C7~C9(II)·P1~P4 모두 형식 그림과 일치",
"이미지의 B2·B5·B8·C10·C12 등 J 겹침 마크는 대표 조각 1개만 그려져 한쪽 다리만 보임, 긴 철근은 가로세로 비율 왜곡. 운곡·Ramp-A 는 형식별 상세 그림이 DXF 안에 있어 추출 후 작성 예정"], 4)
ws.cell(row=r, column=1).fill = PatternFill("solid", fgColor="FFFFF2CC")
row = max(i.anchor._from.row + int(i.height / 20) for i in sh._images) + 6
for part in ("코핑", "기초", "기둥"):
p = CAP / ("도면대조_산외_%s.png" % part)
sh.cell(row=row, column=1, value="산외 %s — 형식 그림 ↔ 모델 대조" % part).font = Font(bold=True, size=12)
im = XLImage(str(p)); w0, h0 = im.width, im.height
im.width, im.height = 1250, int(1250 * h0 / w0); sh.add_image(im, "A%d" % (row + 1)); row += int(im.height / 20) + 4
wb.save(REV / NAME); shutil.copy2(REV / NAME, ORIG / NAME)
sha = lambda p: hashlib.sha256(Path(p).read_bytes()).hexdigest()
print("sha equal:", sha(REV / NAME) == sha(ORIG / NAME), sha(REV / NAME)[:16], len(sh._images))
@@ -0,0 +1,51 @@
"""4개교 전 마크 모델 형상 일람 이미지를 엑셀 새 시트 '형상 일람(모델)'로 넣고 '수정 내역' R-21(점검, 수정 없음)을 기록. 백업(양쪽) → Pier_T → 원본 복사 → SHA 확인."""
import copy, datetime, hashlib, shutil, sys
from pathlib import Path
import openpyxl
from openpyxl.drawing.image import Image as XLImage
from openpyxl.styles import Alignment, Font, PatternFill
ROOT = Path(r"D:\★Pier 자료\프로그램\Pier_T"); REV = ROOT / "검토파일"; ORIG = Path(r"D:\★Pier 자료\심수석님 검토 파일"); NAME = "4개교_공통사항_종합.xlsx"
CAP = REV / "수정후_캡처"
stamp = datetime.date.today().strftime("%Y%m%d")
for d in (REV, ORIG):
shutil.copy2(d / NAME, d / ("4개교_공통사항_종합_백업_%s_형상일람.xlsx" % stamp))
wb = openpyxl.load_workbook(REV / NAME)
ws = wb["수정 내역"]
if any(r[0].value == "R-21" for r in ws.iter_rows(min_row=4)) or "형상 일람(모델)" in wb.sheetnames:
sys.exit("이미 있음")
YEL = PatternFill("solid", fgColor="FFFFF2CC")
def append_like(sheet, values, like_row):
r = sheet.max_row + 1
for j, v in enumerate(values, 1):
c = sheet.cell(row=r, column=j, value=v); s = sheet.cell(row=like_row, column=j)
c.font = copy.copy(s.font); c.fill = copy.copy(s.fill); c.border = copy.copy(s.border); c.alignment = copy.copy(s.alignment); c.number_format = s.number_format
sheet.auto_filter.ref = "A3:%s%d" % (openpyxl.utils.get_column_letter(sheet.max_column), r)
return r
files = sorted(CAP.glob("형상일람_*.png"), key=lambda p: (["운곡", "산외", "옥성", "RampA"].index(p.stem.split("_")[1]), ["기초", "코핑", "기둥", "말뚝"].index(p.stem.split("_")[2])))
r = append_like(ws, ["R-21", "4개교", "철근 형상 전수 점검 (재료표 형식 ↔ 강종별 형상 상세 ↔ 모델) — 모델 형상 일람 작성",
"기초·코핑·기둥·말뚝 전 마크(%d장)" % len(files),
"마크별 형상이 도면 상세와 같은지 한눈에 대조할 자료가 없었음 (재료표 숫자 위주 점검)",
"모델 전 마크의 대표 1본을 2D 로 그린 일람 이미지 작성(시트 '형상 일람(모델)'). 수정은 하지 않음",
0, "사용자 요청 2026-10-27: 산외 B1·B4 지적(→ SD500 형식 I 직선으로 일치, R-20) 후 '4개교 전부 오류가 있을 수 있으니 진행'",
"각 모델 최신본(운곡 수정7, 산외 수정5, 옥성 수정6, Ramp-A 수정6)", "모델 형상 분류(직선 수·호 수·폐합·치수)를 전 마크 추출해 이미지화. 직선 철근/ㄷ자/ㅁ자/갈고리 등 큰 틀은 형식과 일치",
"마크별 상세 대조는 형식·강종별 상세 그림과 1:1 확인 필요(아래 후보 참고): 운곡 C16 형식 II 가 ㄴ자, 산외 C11·C13 조각 중 1 mm 직선 구간, 운곡 C9~C13(IV·X) 폐합형에 J 겹침 미반영(C-3), 재료표 L 의 4J 와 모델 2J 차이"], 4)
ws.cell(row=r, column=1).fill = YEL
sh = wb.create_sheet("형상 일람(모델)")
sh["A1"] = "4개교 철근 모델 형상 일람 — 마크별 대표 1본 (2D 투영). 도면 이형철근 상세(강종별 SD400/SD500)와 같은 형식인지 대조용"
sh["A1"].font = Font(bold=True, size=14)
sh["A2"] = "초록 ● 시작 / 빨강 ■ 끝. 긴 철근은 가로세로 비율을 왜곡해 형상만 보이게 함(칸 아래 표기). 'N=…·조각'은 J 겹침으로 2조각으로 나눈 철근. L(표)=재료표 길이, 모델=중심선 길이, 직선=직선 구간 길이."
row = 4
for p in files:
sh.cell(row=row, column=1, value=p.stem.replace("형상일람_", "").replace("_", " ")).font = Font(bold=True, size=12)
im = XLImage(str(p)); w0, h0 = im.width, im.height
im.width, im.height = 1250, int(1250 * h0 / w0)
sh.add_image(im, "A%d" % (row + 1))
row += int(im.height / 20) + 4
sh.column_dimensions["A"].width = 190
wb.save(REV / NAME); shutil.copy2(REV / NAME, ORIG / NAME)
sha = lambda p: hashlib.sha256(Path(p).read_bytes()).hexdigest()
print("sha equal:", sha(REV / NAME) == sha(ORIG / NAME), sha(REV / NAME)[:16], "sheet images:", len(sh._images), "files", len(files))
@@ -0,0 +1,43 @@
"""운곡교 DXF(3.dxf) 이형철근 상세 ↔ 모델 마크별 대조 이미지 3장 + 운곡 도면↔도면 오류(형식 그림 j 있으나 재료표 J 비어 있음) 기록. 하루 1백업."""
import copy, hashlib, shutil, sys
from pathlib import Path
import openpyxl
from openpyxl.drawing.image import Image as XLImage
from openpyxl.styles import Font, PatternFill
from xlsx_backup_once import backup_once, NAME
ROOT = Path(r"D:\★Pier 자료\프로그램\Pier_T"); REV = ROOT / "검토파일"; ORIG = Path(r"D:\★Pier 자료\심수석님 검토 파일"); CAP = REV / "수정후_캡처"
print("backup:", backup_once())
wb = openpyxl.load_workbook(REV / NAME); ws, sh, hb = wb["수정 내역"], wb["형상 일람(모델)"], wb["교량별 항목 합본"]
if any(r[0].value == "R-27" for r in ws.iter_rows(min_row=4)):
sys.exit("이미 있음")
def append_like(sheet, values, like_row):
r = sheet.max_row + 1
for j, v in enumerate(values, 1):
c = sheet.cell(row=r, column=j, value=v); s = sheet.cell(row=like_row, column=j)
c.font = copy.copy(s.font); c.fill = copy.copy(s.fill); c.border = copy.copy(s.border); c.alignment = copy.copy(s.alignment); c.number_format = s.number_format
sheet.auto_filter.ref = "A3:%s%d" % (openpyxl.utils.get_column_letter(sheet.max_column), r)
return r
YEL = PatternFill("solid", fgColor="FFFFF2CC")
r = append_like(ws, ["R-27", "운곡교", "재료표 형식 ↔ 도면(DXF 3.dxf) 이형철근 상세 형식 그림 ↔ 모델 형상 마크별 대조 (코핑·기초·기둥 전 마크)",
"운곡교 P1 코핑 C1~C16·S1·S2, 기초 B1~B12, 기둥 P1~P6 (이미지 3장)", "형식 그림은 PNG/표만 보고 점검했고 DXF 의 이형철근 상세(I~XVII)와 마크별로 비교한 자료가 없었음",
"DXF 3.dxf 의 이형철근 상세 영역을 렌더(ezdxf)해 형식별로 잘라 모델 형상 옆에 배치(시트 '형상 일람(모델)' 하단). 수정은 하지 않음",
0, "사용자 지시 2026-10-28: DXF 도면이 제1 자료, 도면에서 이미지를 잘라 넣고 도면↔도면·도면↔모델 오류를 엑셀에 작성",
"운곡교p1_수정7_20261026.3dm",
"형식 불일치 없음: VIII(C1~C6) 다리각 98°/96°, VII(C7·C8) 호 2개, IV(C9~C11) 사각 링, II(C16)=ㄴ자(이전 '산외 II ㅁ 과 다름' 의심은 도면이 ㄴ자라 해소), III(C14·C15·S1·S2·B1·B3·B12·P6), XI(B9) 갈고리, I(B4) 직선",
"도면↔도면 오류 D-10 기록(아래 '교량별 항목 합본'): 형식 XII·XIII·X·XVI·VI 그림에는 j 치수가 있으나 재료표 J 열은 비어 있음 → 겹침 반영 불가, 도면 확인 필요"], 4)
ws.cell(row=r, column=1).fill = YEL
r2 = append_like(hb, ["운곡교", "D-10", "B2·B5·B6·B7·B11(XII), B10(XIII), C12·C13(X), B8·P2(XVI), P3(VI)",
"이형철근 상세 형식 그림에 겹침 길이 j 가 그려져 있으나 재료표 J 열이 비어 있음 (표 L 에도 j 가 포함되지 않은 값)",
"도면 형식 그림(DXF 3.dxf) ↔ 도면 재료표(같은 도면)", "J 값 없음 (예: B2 표 L 11,500 ↔ 모델 11,397 로 j 미포함)",
"도면 내부 불일치: 형식 XII·XIII·X·XVI 는 j 포함 형상인데 표에 J 값이 없음", "설계자 확인 필요: j 길이와 위치를 알려 주기 전에는 모델에 겹침을 반영하지 않음(현재 모델은 겹침 없는 단일 철근)",
"도면↔도면 (도면 내부 오류)", "개별 (운곡교)"], hb.max_row)
hb.cell(row=r2, column=9).fill = YEL
row = max(i.anchor._from.row + int(i.height / 20) for i in sh._images) + 6
for part in ("코핑", "기초", "기둥"):
p = CAP / ("도면대조_운곡_%s.png" % part)
sh.cell(row=row, column=1, value="운곡 %s — DXF 형식 그림 ↔ 모델 대조" % part).font = Font(bold=True, size=12)
im = XLImage(str(p)); w0, h0 = im.width, im.height
im.width, im.height = 1250, int(1250 * h0 / w0); sh.add_image(im, "A%d" % (row + 1)); row += int(im.height / 20) + 4
wb.save(REV / NAME); shutil.copy2(REV / NAME, ORIG / NAME)
sha = lambda p: hashlib.sha256(Path(p).read_bytes()).hexdigest()
print("sha equal:", sha(REV / NAME) == sha(ORIG / NAME), sha(REV / NAME)[:16], len(sh._images))
@@ -0,0 +1,71 @@
"""'공통 문제 상세(이미지)' 시트에 I열 '수정 완료' 를 추가하고 C-1~C-7 행별로 수정 결과를 적는다.
사용: python add_수정완료_열.py [대상 xlsx] (기본: 검토파일/4개교_공통사항_종합.xlsx)
I3 이 이미 있으면 중단(이중 적용 방지). 이미지·병합 셀은 건드리지 않는다.
수치 근거: Code/검토수정/결과/*.json, 엑셀 '수정 내역' 시트 R-1~R-9
"""
import copy
import sys
from pathlib import Path
import openpyxl
from openpyxl.styles import Alignment, PatternFill
DEFAULT = Path(r"D:\★Pier 자료\프로그램\Pier_T\검토파일\4개교_공통사항_종합.xlsx")
target = Path(sys.argv[1]) if len(sys.argv) > 1 else DEFAULT
OK = PatternFill("solid", fgColor="FFE2EFDA") # 수정 완료
TMP = PatternFill("solid", fgColor="FFFFF2CC") # 임시 수정
NONE = PatternFill("solid", fgColor="FFEDEDED") # 미수정
PART = PatternFill("solid", fgColor="FFDDEBF7") # 일부 완료·일부 보류
TXT = {
4: (PART, "[일부 완료] 4개 교량 굽힘 반지름을 KDS 24 14 21 기준으로 교체 (2026-10-23~26). "
"H19 R42.75→42.93, H22 R49.5→49.85, H25 R56.25→56.95 (철근 끝점 고정, 호만 커짐 → 철근 1본당 0.08~1.2mm 짧아짐).\n"
"교체 본수(기초 제외): 운곡 390 · 산외 207 · 옥성 561 · Ramp-A 260. 기초 철근은 별도 규칙과 함께 처리: 운곡 155 · 산외 62 · 옥성 214.\n"
"검증: 수정본 전수 스캔 → 기준 미달 호는 형상이 복잡한 102본뿐 (운곡 P3 72 · 옥성 C9·C13 18 · Ramp-A C12 12), 이는 보류.\n"
"상세: '수정 내역' R-1~R-8, '수정 증거(마크별)', 'KDS 직경별 R' 시트"),
5: (PART, "아래 H29 · H25 · H22 · H19 · H16 행별 수정 결과"),
6: (NONE, "[수정 없음] 이미 기준 충족: 모델 R65.25 ≥ KDS 최소 중심선 R 64.56. 4교 전수 스캔에서 H29 미달 호 0개."),
7: (OK, "[수정 완료] H25 R56.25→56.95.\n운곡: C9~C13, 기초 B1·B2 / 옥성: C8~C13 / Ramp-A: C3.\n"
"보류: 옥성 C9·C13 중 18본(파이프 재생성 실패, 형상 복잡)."),
8: (OK, "[수정 완료] H22 R49.5→49.85.\n산외: C7~C10, C15, 기초 B2·B5 / 옥성: C14·C16.\n운곡·Ramp-A 는 H22 굽힘 철근 없음."),
9: (PART, "[일부 완료] H19(S19 포함) R42.75→42.93.\n운곡: S1·S2, C14~C16, 기초 B3·B7·B10 / 산외: P5 / 옥성: S1·S2, C18~C20, 기초 B9~B12 / Ramp-A: C7~C16.\n"
"보류: 운곡 P3 72본(호가 이어진 형상), Ramp-A C12 중 12본."),
10: (TMP, "[임시 수정] 운곡 B9(H16) 위쪽 180° 갈고리 R20.4→24 (KDS H16 최소 중심선 R 23.85), 연장 0→100(임의). 493본.\n"
"도면에 갈고리 R·연장이 없어(도면 오류) 설계자 확인 전 임시 값. 재료표 L 2,155 와 +101mm, 아래 90° 연장 72 < 5db 80 은 유지.\n"
"파일: 운곡교p1_수정6_20261026.3dm. 산외·옥성·Ramp-A H16 은 180° 갈고리 없음."),
11: (NONE, "[미수정] 설계자 확인 필요 — 이음·커플러 각도(90°/270° 가정)와 위치 기준이 정해지지 않아 모델 그대로."),
12: (NONE, "[미수정] 설계자 확인 필요 — 커플러 수량(산외 476 · Ramp-A 115)을 모델에 넣을지 미정."),
13: (NONE, "[미수정] 겹침·갈고리 길이(j, c)를 형상에 넣을지 가산 길이로만 둘지 정책 미정."),
14: (NONE, "[미수정] 재료표 +54 가산 규칙의 적용 범위(길이/폭) 미정."),
15: (NONE, "[미수정] 철근별 개별 길이가 의도인지 설계자 확인 필요."),
16: (NONE, "[미수정] 조립용 철근(UA1/UM) 배치 기준 설계자 확인 필요."),
17: (OK, "[수정 완료 — 운곡·산외·옥성 / Ramp-A 는 해당 없음] 사용자 규칙(2026-10-23·26): 최외각 주철근 중심을 피복(상면 100 / 하면 150)에 두고 나머지는 그 안쪽에 접촉 배치 "
"(같은 높이로 겹치지 않음. 이 시트의 '대안 1: 도면 점 높이' 와는 다른 방식).\n"
"운곡: B5 2127→2100, B1 2073→2072.5, B6·B8 178→150, B2·B4 122→177 (B2 다리 끝 2072.5, 약 54.5mm 짧아짐).\n"
"산외: B1 2422.5→2400, B4 2377.5→2384, B2·B3 127.5→150, B5·B6 172.5→172.\n"
"옥성: B5·B7 2077.5→2071, B6·B8 172.5→179 (B1~B4 는 이미 2100/150).\n"
"저장 후 재측정 값 일치. 남은 확인: 산외 B7 세로철근, 옥성 B12, 운곡 B2 다리 끝 해석 ('미수정·보류' 시트)."),
18: (OK, "위 C-7 행과 같음. ※ 이 행의 캡처는 수정 전 모델입니다."),
19: (OK, "위 C-7 행과 같음. ※ 이 행의 캡처는 수정 전 모델입니다 (수정 후 피복: 운곡 B5 상면 100, B6 하면 150 위치)."),
20: (OK, "위 C-7 행과 같음. ※ 이 행의 캡처는 수정 전 모델입니다."),
}
wb = openpyxl.load_workbook(target)
ws = wb["공통 문제 상세(이미지)"]
if ws["I3"].value:
sys.exit("I3 이 이미 있음 - 중단")
ws["I3"] = "수정 완료 (2026-10-26) ※ 이 시트의 캡처 이미지는 수정 전 모델입니다"
for attr in ("font", "fill", "border", "alignment"):
setattr(ws["I3"], attr, copy.copy(getattr(ws["H3"], attr)))
ws["I3"].alignment = Alignment(wrap_text=True, vertical="center")
for row, (fill, text) in TXT.items():
c = ws.cell(row=row, column=9, value=text)
c.fill = copy.copy(fill)
c.border = copy.copy(ws.cell(row=row, column=8).border)
c.alignment = Alignment(wrap_text=True, vertical="top")
c.font = copy.copy(ws.cell(row=row, column=8).font)
ws.column_dimensions["I"].width = 70
wb.save(target)
print("saved", target)
@@ -0,0 +1,64 @@
"""'공통 문제 상세(이미지)' 시트에 J~M열 '수정 후 캡처'를 만들고 수정 후 이미지를 같은 행의 교량별 열에 넣는다 (2026-10-26).
이미지: 검토파일/수정후_캡처/*.png (make_after_images.py)
J=운곡교, K=산외교, L=옥성교, M=Ramp-A교. 기존 열(C~F)에서 '(해당 없음 …)' 텍스트였던 칸은 같은 텍스트를 J~M 에 복사한다.
J3 이 이미 있으면 중단(이중 적용 방지).
"""
import copy
import sys
from pathlib import Path
import openpyxl
from openpyxl.drawing.image import Image as XLImage
from openpyxl.styles import Alignment
ROOT = Path(r"D:\★Pier 자료\프로그램\Pier_T")
IMG = ROOT / "검토파일" / "수정후_캡처"
XLSX = ROOT / "검토파일" / "4개교_공통사항_종합.xlsx"
COLS = {"운곡교": "J", "산외교": "K", "옥성교": "L", "Ramp-A교": "M"}
BEFORE_COL = {"운곡교": "C", "산외교": "D", "옥성교": "E", "Ramp-A교": "F"}
PLAN = { # row -> {bridge: image file}
6: {"운곡교": "C-1_운곡교_H29_수정후.png", "옥성교": "C-1_옥성교_H29_수정후.png", "Ramp-A교": "C-1_Ramp-A교_H29_수정후.png"},
7: {"운곡교": "C-1_운곡교_H25_수정후.png", "옥성교": "C-1_옥성교_H25_수정후.png", "Ramp-A교": "C-1_Ramp-A교_H25_수정후.png"},
8: {"산외교": "C-1_산외교_H22_수정후.png", "옥성교": "C-1_옥성교_H22_수정후.png"},
9: {"운곡교": "C-1_운곡교_H19_수정후.png", "산외교": "C-1_산외교_H19_수정후.png", "옥성교": "C-1_옥성교_H19_수정후.png", "Ramp-A교": "C-1_Ramp-A교_H19_수정후.png"},
10: {"운곡교": "C-1_운곡교_H16_수정후.png"},
19: {"운곡교": "C-7_정면도_수정후_운곡교.png", "산외교": "C-7_정면도_수정후_산외교.png", "옥성교": "C-7_정면도_수정후_옥성교.png"},
20: {"운곡교": "C-7_단면도_수정후_운곡교.png", "산외교": "C-7_단면도_수정후_산외교.png", "옥성교": "C-7_단면도_수정후_옥성교.png"},
}
wb = openpyxl.load_workbook(XLSX)
ws = wb["공통 문제 상세(이미지)"]
if ws["J3"].value:
sys.exit("J3 이 이미 있음 - 중단")
for br, col in COLS.items():
c = ws["%s3" % col]
c.value = "%s — 수정 후 캡처 (2026-10-26)" % br
for attr in ("font", "fill", "border", "alignment"):
setattr(c, attr, copy.copy(getattr(ws["H3"], attr)))
c.alignment = Alignment(wrap_text=True, vertical="center")
ws.column_dimensions[col].width = 88
added = 0
for row, items in PLAN.items():
for br, col in COLS.items():
if br in items:
p = IMG / items[br]
im = XLImage(str(p))
w0, h0 = im.width, im.height
if row in (19, 20):
im.width, im.height = 620, int(620 * h0 / w0)
else:
im.width, im.height = 600, int(600 * h0 / w0)
ws.add_image(im, "%s%d" % (col, row))
added += 1
else:
t = ws["%s%d" % (BEFORE_COL[br], row)].value
if isinstance(t, str) and t.startswith("("):
c = ws["%s%d" % (col, row)]
c.value = t
c.alignment = Alignment(wrap_text=True, vertical="top")
ws["J5"].value = "※ 수정 후 캡처: C-7 은 수정된 모델의 Rhino Front / Right 뷰 캡처(기초 콘크리트 숨김) + 높이 기준선, C-1 은 수정된 모델의 호 반지름 실측값으로 같은 형식으로 작성"
ws["J5"].alignment = Alignment(wrap_text=True, vertical="top")
wb.save(XLSX)
print("images added:", added)
@@ -0,0 +1,124 @@
"""산외·옥성 기초 전단·세로철근 수정(2026-10-26)을 '수정 내역' 계열 시트에 추가한다.
- 수정 내역: R-10(옥성 B9), R-11(산외 B7), R-12(산외 B9·B10) 행 추가
- 수정 증거(마크별): 같은 철근 행 추가
- 미수정·보류: 산외 B7 행을 '수정 완료'로 갱신, 옥성 B9 연장 부족 행 추가
- 수정 파일·해시: 산외·옥성 수정2 를 '중간본' 으로, 수정3 두 파일을 '최신' 으로 추가
입력: Code/검토수정/결과/c1_shear_fix.json. 같은 R-10 이 이미 있으면 중단(이중 적용 방지).
"""
import copy
import datetime
import hashlib
import json
import sys
from pathlib import Path
import openpyxl
from openpyxl.styles import PatternFill
ROOT = Path(r"D:\★Pier 자료\프로그램\Pier_T")
REV = ROOT / "검토파일"
XLSX = REV / "4개교_공통사항_종합.xlsx"
res = json.loads((ROOT / "Code" / "검토수정" / "결과" / "c1_shear_fix.json").read_text(encoding="utf-8"))
wb = openpyxl.load_workbook(XLSX)
ws = wb["수정 내역"]
if any(r[0].value == "R-10" for r in ws.iter_rows(min_row=4)):
sys.exit("R-10 이 이미 있음 - 중단")
def append_like(sheet, values, like_row):
r = sheet.max_row + 1
for j, v in enumerate(values, 1):
c = sheet.cell(row=r, column=j, value=v)
s = sheet.cell(row=like_row, column=j)
c.font = copy.copy(s.font)
c.fill = copy.copy(s.fill)
c.border = copy.copy(s.border)
c.alignment = copy.copy(s.alignment)
c.number_format = s.number_format
sheet.auto_filter.ref = "A3:%s%d" % (openpyxl.utils.get_column_letter(sheet.max_column), r)
return r
so, ok = res["sanoe"], res["okseong"]
b7, b9s, b10s, b9o = so["sample"]["B7"], so["sample"]["B9"], so["sample"]["B10"], ok["sample"]["B9"]
n7, n9, n10, no9 = so["stat"]["B7_done"], so["stat"]["B9_done"], so["stat"]["B10_done"], ok["stat"]["B9_done"]
rows = [
["R-10", "옥성교", "기초 C형 띠철근 B9 (H19) 갈고리 연장", "B9 (tie-C)",
"양 끝 연장 57.1 / 길이 %.1f (재료표 L 4,763 보다 짧음)" % b9o["len_old"],
"양 끝 연장 %.1f / 길이 %.1f (= 재료표 L)" % (b9o["tail_new"], b9o["len_new"]), no9,
"사용자 승인 2026-10-26: 도면에 값이 있으면 재료표 길이를 따름 → 연장을 늘려 중심선 길이 = 재료표 L. 걸림 높이 126 / 2124 는 바깥 주철근에 이미 걸려 있어 유지",
"옥성교P1_G5_수정3_20261026.3dm",
"저장 직전 문서 확인: 171본 모두 길이 4,763.0, 객체 수 %d → %d 동일, 파이프 부피 오차 0.2%% 이내" % (ok["objects_before"], ok["objects_after"]),
"연장 %.1f < KDS 5db 95.5 (1.5mm 부족) — 재료표 L 을 따른 결과. 설계자 확인" % b9o["tail_new"]],
["R-11", "산외교", "기초 세로철근 B7 (H13) 양 끝 높이", "B7 (H13 세로철근)",
"양 끝 z 166 / 2384 (바깥 주철근 150 / 2400 안쪽) / 길이 %.1f" % b7["len_old"],
"양 끝 z 132.5 / 2414.5 (바깥 주철근에 걸림: 150−11−6.5, 2400+8+6.5) / 길이 %.1f" % b7["len_new"], n7,
"사용자 승인 2026-10-26: 피복 밖으로 나갈 수 있는 철근은 전단·세로철근, 주철근에 걸어줌 (운곡교 B9·옥성교 B9 와 같은 방식)",
"산외교P1 G5_수정3_20261026.3dm",
"저장 직전 문서 확인: 98본 z 범위 132.5~2414.5, 갈고리 R19.5·연장 80.5 유지(KDS H13 최소 R 19.05, 5db 65 만족). 객체 수 %d → %d 동일" % (so["objects_before"], so["objects_after"]),
"도면 B7 값은 [추론](체크무늬 98본, 갈고리 +Y). 길이 %.1f > 재료표 L 2,418 (+47) — 설계자 확인" % b7["len_new"]],
["R-12", "산외교", "기초 중간 직선철근 B9·B10 (H16) 갈고리 연장", "B9, B10",
"연장 76 / 길이 %.1f (재료표 L 7,500)" % b9s["len_old"],
"연장 %.1f / 길이 %.1f (= 재료표 L)" % (b9s["tail_new"], b9s["len_new"]), n9 + n10,
"사용자 승인 2026-10-26: 연장을 늘려 중심선 길이 = 재료표 L (도면에 값이 있으면 재료표를 따름)",
"산외교P1 G5_수정3_20261026.3dm",
"저장 직전 문서 확인: B9 7본·B10 7본 모두 길이 7,500.0, 연장 86.3 ≥ KDS 5db 79.5",
"-"],
]
for row in rows:
append_like(ws, row, 4)
ev = wb["수정 증거(마크별)"]
ev_rows = [
["옥성교", "B9", "H19", "전단철근 갈고리 연장", no9, "연장 57.1 / 길이 %.1f" % b9o["len_old"], "연장 %.1f / 길이 %.1f" % (b9o["tail_new"], b9o["len_new"]),
round((b9o["len_new"] - b9o["len_old"]) * no9, 1), "합계 길이 변화(mm). 재료표 L 4,763 에 맞춤"],
["산외교", "B7", "H13", "세로철근 끝 높이(기초 하단 기준 mm)", n7, "z 166 / 2384, 길이 %.1f" % b7["len_old"], "z 132.5 / 2414.5, 길이 %.1f" % b7["len_new"],
round((b7["len_new"] - b7["len_old"]) * n7, 1), "합계 길이 변화(mm). 바깥 주철근에 걸림"],
["산외교", "B9", "H16", "중간 직선철근 갈고리 연장", n9, "연장 76 / 길이 %.1f" % b9s["len_old"], "연장 %.1f / 길이 %.1f" % (b9s["tail_new"], b9s["len_new"]),
round((b9s["len_new"] - b9s["len_old"]) * n9, 1), "재료표 L 7,500 에 맞춤"],
["산외교", "B10", "H16", "중간 직선철근 갈고리 연장", n10, "연장 76 / 길이 %.1f" % b10s["len_old"], "연장 %.1f / 길이 %.1f" % (b10s["tail_new"], b10s["len_new"]),
round((b10s["len_new"] - b10s["len_old"]) * n10, 1), "재료표 L 7,500 에 맞춤"],
]
for row in ev_rows:
append_like(ev, row, 4)
hold = wb["미수정·보류"]
for r in hold.iter_rows(min_row=4):
if r[0].value == "산외교" and str(r[1].value).startswith("B7"):
r[3].value = "수정 완료(2026-10-26): 양 끝을 바깥 주철근에 걸리게 옮김 (z 132.5 / 2414.5)"
r[4].value = "도면 값이 [추론]이고 길이 2,465.3 이 재료표 L 2,418 보다 47mm 김. '수정 내역' R-11"
r[5].value = "설계자 확인 (도면 B7 형상·길이)"
append_like(hold, ["옥성교", "B9 (H19 C형 띠철근)", "171본", "연장 93.9 < KDS 5db 95.5 (1.5mm 부족)",
"재료표 L 4,763 에 맞춘 결과. 연장을 KDS 로 키우면 L 초과. '수정 내역' R-10", "설계자 확인 (L 과 KDS 중 우선)", "R-10"], 4)
append_like(hold, ["산외·옥성교", "B8·B10·B11·B12 등 겹침 이음이 있는 띠·루프철근", "-", "재료표 L 에 겹침 J 가 있으나 형상에 없음",
"공통 문제 C-3(겹침 길이를 형상에 넣을지 정책 미정)이라 이번에는 수정하지 않음", "정책 결정", "C-3"], 4)
# 파일·해시
fs = wb["수정 파일·해시"]
def sha(p):
h = hashlib.sha256()
with open(p, "rb") as f:
for blk in iter(lambda: f.read(1 << 20), b""):
h.update(blk)
return h.hexdigest()
for r in fs.iter_rows(min_row=4):
if r[1].value in ("검토파일/검토_산외교P1/산외교P1 G5_수정2_20261026.3dm", "검토파일/검토_옥성교P1/옥성교P1_G5_수정2_20261026.3dm"):
r[3].value = "중간본"
r[3].fill = PatternFill(fill_type=None)
new_files = [("산외교", "검토_산외교P1/산외교P1 G5_수정3_20261026.3dm", "기초 전단·세로철근(B7 걸기, B9·B10 연장) 포함 — 전체 수정 포함"),
("옥성교", "검토_옥성교P1/옥성교P1_G5_수정3_20261026.3dm", "기초 C형 띠철근 B9 연장 포함 — 전체 수정 포함")]
latest_fill = copy.copy(fs.cell(row=9, column=4).fill)
for b, rel, what in new_files:
p = REV / rel
stt = p.stat()
r = append_like(fs, [b, "검토파일/" + rel, what, "최신", round(stt.st_size / 1e6, 1),
datetime.datetime.fromtimestamp(stt.st_mtime).strftime("%Y-%m-%d %H:%M"), sha(p)], 4)
fs.cell(row=r, column=4).fill = PatternFill("solid", fgColor="FFE2EFDA")
wb.save(XLSX)
print("saved", XLSX)
@@ -0,0 +1,160 @@
"""후속 수정(2026-10-26: A 굽힘 R 마무리, C 운곡 B2 다리 끝 2100, D 갈고리 c·d 도면 값)을 엑셀에 반영한다.
- 수정 내역: R-13(A), R-14(C), R-15(D) 추가, R-1·R-3·R-4 비고에 후속 완료 표시
- 수정 증거(마크별): 같은 철근 행 추가
- 미수정·보류: 완료된 행 갱신, 옥성 B9 a 범위 메모 추가
- 수정 파일·해시: 새 파일 5개 추가, 이전 최신본은 '중간본'
- 공통 문제 상세(이미지) I열: C-1 행(4·7·9) 문구 갱신
같은 R-13 이 이미 있으면 중단(이중 적용 방지).
"""
import copy
import datetime
import hashlib
import json
import sys
from pathlib import Path
import openpyxl
from openpyxl.styles import PatternFill
ROOT = Path(r"D:\★Pier 자료\프로그램\Pier_T")
REV = ROOT / "검토파일"
RES = ROOT / "Code" / "검토수정" / "결과"
XLSX = REV / "4개교_공통사항_종합.xlsx"
fx1 = json.loads((RES / "c1_fix_remaining_ungok_okseong.json").read_text(encoding="utf-8"))
fx2 = json.loads((RES / "c1_fix_remaining_rampa.json").read_text(encoding="utf-8"))
hk = json.loads((RES / "c1_hook_cd.json").read_text(encoding="utf-8"))
wb = openpyxl.load_workbook(XLSX)
ws = wb["수정 내역"]
if any(r[0].value == "R-13" for r in ws.iter_rows(min_row=4)):
sys.exit("R-13 이 이미 있음 - 중단")
GREEN = PatternFill("solid", fgColor="FFE2EFDA")
GRAY = PatternFill("solid", fgColor="FFD9D9D9")
def append_like(sheet, values, like_row):
r = sheet.max_row + 1
for j, v in enumerate(values, 1):
c = sheet.cell(row=r, column=j, value=v)
s = sheet.cell(row=like_row, column=j)
c.font = copy.copy(s.font)
c.fill = copy.copy(s.fill)
c.border = copy.copy(s.border)
c.alignment = copy.copy(s.alignment)
c.number_format = s.number_format
sheet.auto_filter.ref = "A3:%s%d" % (openpyxl.utils.get_column_letter(sheet.max_column), r)
return r
u, o, ra = fx1["ungok"], fx1["okseong"], fx2["rampa"]
p3, c9c13, c12, b2 = u["stat"]["P3_done"], o["stat"]["C9_done"] + o["stat"]["C13_done"], ra["stat"]["C12_done"], u["stat"]["B2_done"]
hp5, hp3, hp31 = hk["okseong"]["sample"]["P5"], hk["rampa"]["sample"]["P3"], hk["rampa"]["sample"]["P3-1"]
n_p5, n_p3, n_p31 = hk["okseong"]["stat"]["P5_done"], hk["rampa"]["stat"]["P3_done"], hk["rampa"]["stat"]["P3-1_done"]
rows = [
["R-13", "운곡·옥성·Ramp-A", "굽힘 반지름(C-1) 마무리 — 형상이 복잡해 보류했던 철근",
"운곡 P3(H19 링), 옥성 C9·C13(H25), Ramp-A C12(H19)", "H19 R42.75 / H25 R56.25",
"H19 R42.93 / H25 R56.95", p3 + c9c13 + c12,
"사용자 승인 2026-10-26(창 선택 A). 운곡 P3: 호가 이어진 형상이라 '시작점·접선 고정, 호만 키우고 뒤를 평행 이동' 방식(철근 끝 이동 최대 %.2f mm). 옥성·Ramp-A: 기존 모서리 방식 + 파이프 생성 설정 변경(원래 곡선도 기본 설정으로는 실패)" % u["end_shift_mm"]["max"],
"운곡교p1_수정7_20261026.3dm / 옥성교P1_G5_수정4_20261026.3dm / ramp-A G5_수정2_20261026.3dm",
"저장 직전 문서 재스캔: 부족 호 운곡 P3 144 → 0, 옥성 C9·C13 90 → 0, Ramp-A C12 60 → 0. 객체 수 동일(3,236 / 3,862 / 2,255). 파이프 부피 ±0.5% 이내",
"이로써 4교 모든 굽힘의 중심선 R 이 KDS 최소(모델 파이프 기준) 이상"],
["R-14", "운곡교", "기초 U자 철근 B2 다리 끝 해석 통일", "B2 (S25)", "다리 끝 z 2072.5 (B1 높이)",
"다리 끝 z 2100 (바깥 상면 철근선, 산외·옥성과 동일 해석)", b2,
"사용자 승인 2026-10-26(창 선택 C): 도면 U자 다리 길이 = 하면선~상면선 [추론]",
"운곡교p1_수정7_20261026.3dm", "저장 직전 문서 확인: 38본 다리 끝 z 2100 (이동 전 2072.5 확인 후 적용)",
"다리가 약 27.5mm 길어져 재료표 b 1,950 과의 차이는 약 27mm 로 줄어듦"],
["R-15", "옥성·Ramp-A", "갈고리 c·d 도면 값 적용 (도면에 r·c·d 가 있는 철근)",
"옥성 P5(H16), Ramp-A P3(H16)·P3-1(H16)",
"모델: 135° 호 R24 + 곧은 구간 약 150 (c·d 정의와 다름)",
"P5: r60·호 134.65°(c 141)·d 80 / P3: r60·호 134.65°(c 141)·d 100 / P3-1: r135·호 70.03°(c 165)·d 150",
n_p5 + n_p3 + n_p31,
"사용자 지시 2026-10-26: 도면에 있으면 도면을 따르고 없으면 KDS. 도면 상세 행의 L = a+b+c+d (c = 호 길이, 호 각도 = c ÷ r, d = 곧은 구간) 로 확인",
"옥성교P1_G5_수정5_20261026.3dm / ramp-A G5_수정3_20261026.3dm",
"저장 직전 문서 확인: 호 반지름·각도·호 길이·곧은 구간이 도면과 일치 (P5 호 길이 141.0 · P3 141.0 · P3-1 165.0). 객체 수 동일",
"KDS: r 이 H16 최소 23.9 이상, d 80(5db 79.5)·100·150 은 5db 이상. P3-1 갈고리는 약 70° 로 도면에 따름 [도면 c÷r]"],
]
for row in rows:
r = append_like(ws, row, 4)
ws.cell(row=r, column=1).fill = GREEN
for r in ws.iter_rows(min_row=4):
if r[0].value in ("R-1", "R-3", "R-4"):
r[10].value = str(r[10].value or "") + " → 2026-10-26 후속 수정 R-13 으로 보류분 완료"
ev = wb["수정 증거(마크별)"]
ev_rows = [
["운곡교", "P3", "H19", "굽힘 반지름(C-1) 마무리", p3, "R 42.75", "R 42.93", None, "시작점·접선 고정 + 뒤쪽 평행 이동. 끝 이동 %.2f mm. 부족 호 144 → 0" % u["end_shift_mm"]["max"]],
["옥성교", "C9", "H25", "굽힘 반지름(C-1) 마무리", o["stat"]["C9_done"], "R 56.25", "R 56.95", None, "파이프 설정 fitRail=False. 부족 호 50 → 0"],
["옥성교", "C13", "H25", "굽힘 반지름(C-1) 마무리", o["stat"]["C13_done"], "R 56.25", "R 56.95", None, "파이프 설정 fitRail=False. 부족 호 40 → 0"],
["Ramp-A교", "C12", "H19", "굽힘 반지름(C-1) 마무리", c12, "R 42.75", "R 42.93", None, "파이프 설정 fitRail=False. 부족 호 60 → 0"],
["운곡교", "B2", "S25", "기초 철근 U자 다리 끝(기초 하단 기준 mm)", b2, "다리 끝 z 2072.5", "다리 끝 z 2100", 27.5, "다리 길이 +27.5 (본당)"],
["옥성교", "P5", "H16", "갈고리 c·d 도면 값", n_p5, "135° R24 + 곧은 구간 약 150 / 길이 %.1f" % hp5["old_len"], "R60 · %.2f° · 호 %.1f · d %.1f / 길이 %.1f" % (hp5["arc_deg"], hp5["arc_len"], hp5["tail"], hp5["new_len"]), round((hp5["new_len"] - hp5["old_len"]) * n_p5, 1), "도면 r60 c141 d80"],
["Ramp-A교", "P3", "H16", "갈고리 c·d 도면 값", n_p3, "135° R24 + 곧은 구간 / 길이 %.1f" % hp3["old_len"], "R60 · %.2f° · 호 %.1f · d %.1f / 길이 %.1f" % (hp3["arc_deg"], hp3["arc_len"], hp3["tail"], hp3["new_len"]), round((hp3["new_len"] - hp3["old_len"]) * n_p3, 1), "도면 r60 c141 d100"],
["Ramp-A교", "P3-1", "H16", "갈고리 c·d 도면 값", n_p31, "135° R24 + 곧은 구간 / 길이 %.1f" % hp31["old_len"], "R135 · %.2f° · 호 %.1f · d %.1f / 길이 %.1f" % (hp31["arc_deg"], hp31["arc_len"], hp31["tail"], hp31["new_len"]), round((hp31["new_len"] - hp31["old_len"]) * n_p31, 1), "도면 r135 c165 d150 (호 각도 c÷r = 70°)"],
]
for row in ev_rows:
append_like(ev, row, 4)
hold = wb["미수정·보류"]
for r in hold.iter_rows(min_row=4):
k = (str(r[0].value), str(r[1].value))
if k == ("운곡교", "P3 (H19 링)") or k == ("옥성교", "C9·C13 (H25)") or k == ("Ramp-A교", "C12 (H19)"):
r[3].value = "수정 완료(2026-10-26): 굽힘 R 을 KDS 최소 이상으로 다시 만듦"
r[4].value = "'수정 내역' R-13. " + str(r[4].value)
r[5].value = "-"
if k == ("운곡교", "B2 (S25 U자)"):
r[3].value = "수정 완료(2026-10-26): 다리 끝을 2100 으로 통일"
r[4].value = "'수정 내역' R-14. 산외·옥성과 같은 해석"
r[5].value = "-"
append_like(hold, ["옥성교", "B9 (H19 C형 띠철근)", "171본", "도면 상세 a=586~548 은 범위값(모델은 평균 567 고정)",
"사용자 설명: 재료표를 보고 방향 길이에 따라 J 값이 들어가야 함. 도면 B9 행에는 J 가 없고 a 범위(586~548)만 있어 어느 방향·어떤 규칙으로 a 가 변하는지 미확인 → 수정하지 않음",
"a 범위가 변하는 방향·규칙 확인(도면 위치 지정)", "R-10 취소 이후 미결"], 4)
fs = wb["수정 파일·해시"]
def sha(p):
h = hashlib.sha256()
with open(p, "rb") as f:
for blk in iter(lambda: f.read(1 << 20), b""):
h.update(blk)
return h.hexdigest()
old_latest = {"운곡교p1_수정6_20261026.3dm", "옥성교P1_G5_수정2_20261026.3dm", "ramp-A G5_수정_20261023.3dm"}
for r in fs.iter_rows(min_row=4):
name = str(r[1].value).split("/")[-1]
if name in old_latest and r[3].value == "최신":
r[3].value = "중간본"
r[3].fill = PatternFill(fill_type=None)
new_files = [
("운곡교", "철근 모델랑 운곡교P1_바이브코딩/운곡교p1_수정7_20261026.3dm", "P3 굽힘 R 마무리 + B2 다리 끝 2100 — 전체 수정 포함", "최신"),
("옥성교", "검토_옥성교P1/옥성교P1_G5_수정4_20261026.3dm", "C9·C13 굽힘 R 마무리", "중간본"),
("옥성교", "검토_옥성교P1/옥성교P1_G5_수정5_20261026.3dm", "P5 갈고리 도면 값 — 전체 수정 포함(전단철근 수정3 제외)", "최신"),
("Ramp-A교", "Ramp-A교P1/ramp-A G5_수정2_20261026.3dm", "C12 굽힘 R 마무리", "중간본"),
("Ramp-A교", "Ramp-A교P1/ramp-A G5_수정3_20261026.3dm", "P3·P3-1 갈고리 도면 값 — 전체 수정 포함", "최신"),
]
for b, rel, what, st in new_files:
p = REV / rel
stt = p.stat()
r = append_like(fs, [b, "검토파일/" + rel, what, st, round(stt.st_size / 1e6, 1),
datetime.datetime.fromtimestamp(stt.st_mtime).strftime("%Y-%m-%d %H:%M"), sha(p)], 4)
if st == "최신":
fs.cell(row=r, column=4).fill = GREEN
else:
fs.cell(row=r, column=4).fill = PatternFill(fill_type=None)
ws2 = wb["공통 문제 상세(이미지)"]
ws2["I4"].value = ("[완료] 4개 교량 굽힘 반지름을 KDS 24 14 21 기준으로 교체 (2026-10-23~26). H19 R42.75→42.93, H22 R49.5→49.85, H25 R56.25→56.95 (철근 끝점 고정, 호만 커짐 → 철근 1본당 0.08~1.2mm 짧아짐).\n"
"교체 본수(기초 제외): 운곡 390+P3 72 · 산외 207 · 옥성 561+18 · Ramp-A 260+12. 기초 철근은 별도 규칙과 함께 처리: 운곡 155 · 산외 62 · 옥성 214.\n"
"검증: 수정본 전수 스캔 → 4교 모든 굽힘 호가 KDS 최소 중심선 R 이상 (기준 미달 호 0개).\n"
"상세: '수정 내역' R-1~R-8, R-13, '수정 증거(마크별)', 'KDS 직경별 R' 시트")
ws2["I4"].fill = copy.copy(GREEN)
t7 = str(ws2["I7"].value).split("\n보류")[0]
ws2["I7"].value = t7 + "\n(후속 수정 R-13 으로 옥성 C9·C13 18본도 완료)"
t9 = str(ws2["I9"].value).split("\n보류")[0]
ws2["I9"].value = t9.replace("[일부 완료]", "[수정 완료]") + "\n(후속 수정 R-13 으로 운곡 P3 72본·Ramp-A C12 12본도 완료)"
ws2["I9"].fill = copy.copy(GREEN)
wb.save(XLSX)
print("saved")
+30
View File
@@ -0,0 +1,30 @@
# step script: summarise a model (runs inside Rhino, python3). Globals: OUT
import json, collections
import Rhino
doc = __rhino_doc__
lay = {}
for l in doc.Layers:
lay[str(l.Index)] = l.FullPath
cnt = collections.Counter()
samples = {}
st = Rhino.DocObjects.ObjectEnumeratorSettings()
st.HiddenObjects = True
st.LockedObjects = True
st.NormalObjects = True
st.ReferenceObjects = True
for o in doc.Objects.GetObjectList(st):
a = o.Attributes
key = (lay.get(str(a.LayerIndex), "?"), str(o.Geometry.ObjectType))
cnt[key] += 1
if key not in samples:
us = {k: a.GetUserString(k) for k in a.GetUserStrings().AllKeys} if a.GetUserStrings() else {}
s = {"name": a.Name, "userstrings": us}
g = o.Geometry
if isinstance(g, Rhino.Geometry.Curve):
s["curve"] = {"len": g.GetLength(), "type": type(g).__name__, "closed": g.IsClosed}
if isinstance(g, Rhino.Geometry.PolyCurve):
s["curve"]["segs"] = [type(g.SegmentCurve(i)).__name__ for i in range(g.SegmentCount)]
samples[key] = s
res = {"enum_count": sum(cnt.values()), "units": str(doc.ModelUnitSystem), "total": doc.Objects.Count,
"layers": [{"layer": k[0], "type": k[1], "count": v, "sample": samples[k]} for k, v in sorted(cnt.items())]}
json.dump(res, open(OUT, "w", encoding="utf-8"), ensure_ascii=False, indent=1)
@@ -0,0 +1,318 @@
"""4개교_공통사항_종합.xlsx 에 '수정 내역' 계열 시트 5개를 추가하고 M-14(B9) 행을 갱신한다.
입력: Code/검토수정/결과/*.json (이번 수정 작업의 실행 결과), 검토파일 안의 모델 파일(해시 계산)
출력: 검토파일/4개교_공통사항_종합.xlsx (수정 전 파일은 *_백업_*.xlsx 로 보관)
같은 이름의 시트가 이미 있으면 중단한다(이중 적용 방지).
"""
import copy
import datetime
import hashlib
import json
import sys
from pathlib import Path
import openpyxl
from openpyxl.styles import Alignment, Border, Font, PatternFill, Side
ROOT = Path(r"D:\★Pier 자료\프로그램\Pier_T")
REV = ROOT / "검토파일"
RES = ROOT / "Code" / "검토수정" / "결과"
XLSX = REV / "4개교_공통사항_종합.xlsx"
NEW_SHEETS = ["수정 내역", "수정 증거(마크별)", "KDS 직경별 R", "미수정·보류", "수정 파일·해시"]
def jload(name):
return json.loads((RES / name).read_text(encoding="utf-8"))
apply_ = jload("c1_apply.json")
b9 = jload("c1_b9_ungok.json")
kds = jload("c1_kds_scan.json")
foot_u = jload("c1_footing_ungok3.json")
foot_o = jload("c1_footing_other.json")
wb = openpyxl.load_workbook(XLSX)
if any(n in wb.sheetnames for n in NEW_SHEETS):
sys.exit("이미 수정 내역 시트가 있다 - 중단")
ref = wb["개별 항목"]
HEAD_FILL = copy.copy(ref["A3"].fill)
HEAD_FONT = copy.copy(ref["A3"].font)
thin = Side(style="thin", color="FF999999")
BORDER = Border(left=thin, right=thin, top=thin, bottom=thin)
WRAP = Alignment(wrap_text=True, vertical="top")
TITLE_FONT = copy.copy(ref["A1"].font)
FILL_OK = PatternFill("solid", fgColor="FFE2EFDA")
FILL_HOLD = PatternFill("solid", fgColor="FFFFF2CC")
FILL_WARN = PatternFill("solid", fgColor="FFF8CBAD")
def make_sheet(title, heading, note, headers, rows, widths, fills=None):
ws = wb.create_sheet(title)
ws["A1"] = heading
ws["A1"].font = TITLE_FONT
ws["A2"] = note
ws["A2"].alignment = Alignment(wrap_text=False, vertical="top")
for j, h in enumerate(headers, 1):
c = ws.cell(row=3, column=j, value=h)
c.fill = copy.copy(HEAD_FILL)
c.font = copy.copy(HEAD_FONT)
c.border = BORDER
c.alignment = Alignment(wrap_text=True, vertical="center")
for i, row in enumerate(rows, 4):
for j, v in enumerate(row, 1):
c = ws.cell(row=i, column=j, value=v)
c.alignment = WRAP
c.border = BORDER
if fills and fills.get((i - 4, j - 1)):
c.fill = copy.copy(fills[(i - 4, j - 1)])
for j, w in enumerate(widths, 1):
ws.column_dimensions[openpyxl.utils.get_column_letter(j)].width = w
ws.freeze_panes = "A4"
ws.auto_filter.ref = "A3:%s%d" % (openpyxl.utils.get_column_letter(len(headers)), 3 + len(rows))
return ws
# ---------------------------------------------------------------- 수정 내역 (요약)
def c1_row(code, bridge, key, marks, rbefore, rafter, file):
v = apply_[key]
n = v["stat"]["replaced"]
sb, sa = v["short_before"], v["short_after"]
hold = []
if v["stat"].get("skipped_complex"):
hold.append("형상 복잡 %d본(P3) 보류" % v["stat"]["skipped_complex"])
if v["stat"].get("skipped_pipe_fail"):
hold.append("파이프 재생성 실패 %d본 보류" % v["stat"]["skipped_pipe_fail"])
if v["stat"].get("held_footing"):
hold.append("기초 철근 %d본은 별도 규칙으로 처리" % v["stat"]["held_footing"])
ver = ("저장 직전 문서 재스캔: 기초 제외 부족 호 %d → %d개. 객체 수 %d → %d(동일). 새 파이프 부피 = π·r²·L 대비 ±0.2%% 이내(교체 전수)." %
(sb["other"], sa.get("other", 0), v["objects_before"], v["objects_after"]))
return [code, bridge, "굽힘 반지름(C-1)", marks, rbefore, rafter, n,
"KDS 24 14 21 표 4.5-1 (내면지름 ≥ 3.5db, D16 이하 2db), 공칭 직경 기준. 사용자 승인 2026-10-23(창 선택). 공통 문제 C-1 대안 1(권장)",
file, ver, "; ".join(hold)]
rows = [
c1_row("R-1", "운곡교", "ungok", "S1·S2, C9~C16 (H19·H25)", "H19 R42.75 / H25 R56.25", "H19 R42.93 / H25 R56.95",
"운곡교p1_수정_20261023.3dm (이후 수정3·수정6 에 포함)"),
c1_row("R-2", "산외교", "sanoe", "C7~C10, C15, P5 (H22·H19)", "H22 R49.5 / H19 R42.75", "H22 R49.85 / H19 R42.93",
"산외교P1 G5_수정_20261023.3dm (이후 수정2 에 포함)"),
c1_row("R-3", "옥성교", "okseong", "S1·S2, C8~C14, C16, C18~C20 (H19·H22·H25)", "H19 R42.75 / H22 R49.5 / H25 R56.25",
"H19 R42.93 / H22 R49.85 / H25 R56.95", "옥성교P1_G5_수정_20261023.3dm (이후 수정2 에 포함)"),
c1_row("R-4", "Ramp-A교", "rampa", "C3, C7~C16 (H19·H25)", "H19 R42.75 / H25 R56.25", "H19 R42.93 / H25 R56.95",
"ramp-A G5_수정_20261023.3dm"),
["R-5", "운곡교", "기초 철근 높이·피복 (사용자 규칙 2026-10-23)",
"B5(S29 상면 X), B1(S25 상면 Y), B6·B8(S29 하면 X), B2·B4(S25 하면 Y)",
"기초 하단 기준 z: B5 2127 / B1 2073 / B6·B8 178 / B2·B4 122 (B2 다리 끝 2072, B6 다리 끝 2128)",
"B5 2100 / B1 2072.5 / B6·B8 150 / B2·B4 177 (B2 다리 끝 2072.5, B6 다리 끝 2100)",
"이동 %d본 (B5 %d, B1 %d, B6 %d, B8 %d, B2 %d, B4 %d) + 굽힘 R 보정 %d본 (B1·B2·B3·B7·B10)" % (
sum(foot_u["stat"].get(m + "_done", 0) for m in ("B5", "B1", "B6", "B8", "B2", "B4")),
foot_u["stat"]["B5_done"], foot_u["stat"]["B1_done"], foot_u["stat"]["B6_done"], foot_u["stat"]["B8_done"],
foot_u["stat"]["B2_done"], foot_u["stat"]["B4_done"],
sum(foot_u["stat"].get(m + "_done", 0) for m in ("B1", "B2", "B3", "B7", "B10"))),
"사용자 지시 2026-10-23·26: 최외각 주철근(H29 B5·B6) 중심으로 피복 산정(상면 100 / 하면 150), 나머지 철근은 그 안쪽에 접촉 배치. "
"교축·교직 직경이 다르면 계산서 확인·설계자 문의 필요 사항",
"운곡교p1_수정3_20261023.3dm (이후 수정6 에 포함)",
"저장 후 재측정 z 범위(기초 하단 기준): B1 1872.5~2072.5, B2 177~2072.5, B4 177, B5 1900~2100, B6 150~2100, B8 150. 객체 수 3,236 동일.",
"B2 U자 다리 약 54.5mm 짧아짐(다리 끝을 B1 높이 2072.5 로 맞춤) → 재료표 b 1,950 과 다름. 설계자 확인"],
["R-6", "산외교", "기초 철근 높이·피복 (같은 규칙, 직경 동일: 상면 H16 / 하면 H22)",
"B1·B4(H16 상면), B2·B3(H22 하면 바깥), B5·B6(H22 하면 안쪽)",
"z: B1 2422.5 / B4 2377.5 / B2·B3 127.5 / B5·B6 172.5 (기초 하단 기준, 높이 2,500)",
"B1 2400 / B4 2384 / B2·B3 150 / B5·B6 172 (B2 다리 끝 2400, B5 다리 끝 2400)",
"이동 180본 (B1 31, B4 31, B3 28, B2 31, B6 28, B5 31) + 굽힘 R 보정 B2·B5 62본",
"사용자 규칙(운곡교와 동일) + 도면 U자 다리 길이 = 하면선~상면선(2,250) 로 해석 [추론]",
"산외교P1 G5_수정2_20261026.3dm",
"저장 후 재측정 z: B1 2400, B4 2384, B2 150~2400, B3 150, B5 172~2400, B6 172. 객체 수 2,004 동일.",
"B5 다리 22mm 짧아짐. B7(H13 세로철근 166~2384)은 주철근 사이에 놓여 있어 미수정 — 설계자 확인"],
["R-7", "옥성교", "기초 철근 높이·피복 (같은 규칙, 전부 H29)",
"B5·B7(상면 안쪽), B6·B8(하면 안쪽). B1~B4 는 이미 2100 / 150 이라 그대로. 굽힘 R: B9~B12(H19)",
"z: B5·B7 2077.5 / B6·B8 172.5 (B6 다리 끝 2122.5) — 바깥층과 22.5mm 차이라 H29 끼리 6.5mm 겹침",
"B5·B7 2071 / B6·B8 179 (다리 끝 2100). 접촉 배치",
"이동 150본 (B5 38, B7 37, B6 38, B8 37) + 굽힘 R 보정 B9 171, B10 5, B11 19, B12 19 = 214본",
"사용자 규칙 2026-10-23·26 (직경 동일 → 도면 기준 최외각 B1~B4 유지)",
"옥성교P1_G5_수정2_20261026.3dm",
"저장 후 재측정 z: B5·B7 1096~2071, B6·B8 179~2100, B1·B3 1200~2100, B2·B4 150~1950. 객체 수 3,862 동일.",
"B6·B8 다리 29mm 짧아짐. B12 는 도면 점보다 19mm 높음(엑셀 M-12)이라 이번 규칙과 별개로 미수정"],
["R-8", "운곡교", "기초 전단철근 B9 갈고리 (도면에 갈고리 R·연장 없음 = 도면 오류, 임시 수정)",
"B9 (H16) 위쪽 180° 갈고리",
"R20.4(c 64 를 반원 호 길이로 해석), 연장 0 / 길이 2,144.7 / 합계 1,057.3 m",
"R24 (KDS H16 최소 중심선 R 23.85, 모델 H16 굽힘 24.0 과 동일), 연장 100 (임의) / 길이 2,256.1 / 합계 %.1f m / 갈고리 위쪽 피복 %.1f mm" % (b9["total_len_new_m"], b9["min_cover_above_hook"]),
b9["stat"]["replaced"],
"사용자 결정 2026-10-26: 주철근 H29 에 걸리는 B9(H16) 갈고리를 KDS 기준 R 로, 연장 C 는 임의 100. 도면에 값이 있는 경우는 도면 재료표 값 따름(a 1,995, 아래 90° b 96 유지). "
"중간 시도 R65·150(수정4), R45·100(수정5)은 폐기",
"운곡교p1_수정6_20261026.3dm",
"저장된 수정6 파일을 다시 열어 확인(c1_b9_verify): 493본 모두 호 R24(90°)+R24(180°), 마지막 구간 100, 길이 2,256.1, 속성 b9_hook_fix 986개, 객체 수 3,236 동일.",
"재료표 L 2,155 와 약 101mm 차이. 아래 90° 갈고리 연장 72 < 5db 80 (도면 b 96 에서 나온 값이라 유지). 설계자 확인 전 임시 값"],
["R-9", "4개교", "모델 안 수정 기록",
"수정된 철근 객체·문서 속성",
"수정 기록 없음", "객체 사용자 문자열 bend_r_fix / footing_fix / b9_hook_fix (날짜·내용) + 문서 문자열 수정일·수정내용",
"-", "사용자 지시 2026-10-23: 모델에도 수정 날짜를 남길 것",
"각 수정 모델 파일", "수정본 재로드 후 문자열 확인 (B9: 986개 객체에 b9_hook_fix, 수정일 2026-10-26)",
"운곡교 수정_20261023 은 원본이 꺼 둔 기초 철근 레이어 38개를 켜서 저장(검토완료 모델과 표시 동일)"],
]
fills = {}
for i in range(len(rows)):
fills[(i, 0)] = FILL_OK
make_sheet("수정 내역", "4개교 모델 수정 내역 — 공통사항 (작성 2026-10-26)",
"수정은 모두 새 파일에 저장했고 원본·검토완료 모델은 그대로 둠. 근거 데이터 = Code/검토수정/결과/*.json, 실행 스크립트 = Code/검토수정/스크립트/*.py",
["번호", "교량", "수정 항목", "대상 마크", "수정 전", "수정 후", "본수", "근거(규칙·결정)", "결과 파일", "검증(방법·결과)", "비고·남은 문제"],
rows, [7, 9, 24, 34, 38, 38, 26, 48, 30, 48, 44], fills)
# ---------------------------------------------------------------- 수정 증거(마크별)
OLD_R = {"H19": 42.75, "H22": 49.5, "H25": 56.25}
NEW_R = {"H19": 42.93, "H22": 49.85, "H25": 56.95}
BR = {"ungok": "운곡교", "sanoe": "산외교", "okseong": "옥성교", "rampa": "Ramp-A교"}
ev = []
for key, v in apply_.items():
if not isinstance(v, dict):
continue
for mk, x in v["per_mark"].items():
mark, dia = mk.split("/")
ev.append([BR[key], mark, dia, "굽힘 반지름(C-1)", x["bars"], "R %.2f" % OLD_R[dia], "R %.2f" % NEW_R[dia],
x["sum_dlen_mm"], "수정 전후 중심선 길이 차 합계(mm, 철근 끝점 고정이라 호만 커져 짧아짐). 저장 직전 재스캔 부족 호 0"])
foot_rows = [
("운곡교", "B5", "S29", 32, "z 2127 (상면 X)", "z 2100", -27.0),
("운곡교", "B1", "S25", 38, "z 2073 (상면 Y)", "z 2072.5", -0.5),
("운곡교", "B6", "S29", 32, "z 178 (하면 X, 다리 끝 2128)", "z 150 (다리 끝 2100)", -28.0),
("운곡교", "B8", "S29", 29, "z 178", "z 150", -28.0),
("운곡교", "B2", "S25", 38, "z 122 (다리 끝 2072)", "z 177 (다리 끝 2072.5)", 55.0),
("운곡교", "B4", "S25", 35, "z 122", "z 177", 55.0),
("산외교", "B1", "H16", 31, "z 2422.5", "z 2400", -22.5),
("산외교", "B4", "H16", 31, "z 2377.5", "z 2384", 6.5),
("산외교", "B3", "H22", 28, "z 127.5", "z 150", 22.5),
("산외교", "B2", "H22", 31, "z 127.5 (다리 끝 2377.5)", "z 150 (다리 끝 2400)", 22.5),
("산외교", "B6", "H22", 28, "z 172.5", "z 172", -0.5),
("산외교", "B5", "H22", 31, "z 172.5 (다리 끝 2422.5)", "z 172 (다리 끝 2400)", -0.5),
("옥성교", "B5", "H29", 38, "z 2077.5", "z 2071", -6.5),
("옥성교", "B7", "H29", 37, "z 2077.5", "z 2071", -6.5),
("옥성교", "B6", "H29", 38, "z 172.5 (다리 끝 2122.5)", "z 179 (다리 끝 2100)", 6.5),
("옥성교", "B8", "H29", 37, "z 172.5 (다리 끝 2122.5)", "z 179 (다리 끝 2100)", 6.5),
]
for b, m, d, n, bef, aft, dz in foot_rows:
ev.append([b, m, d, "기초 철근 높이(기초 하단 기준 mm)", n, bef, aft, dz, "이동량 mm. 저장 후 재측정 z 범위가 목표와 일치"])
rf = [("운곡교", "B1", "S25", 38), ("운곡교", "B2", "S25", 38), ("운곡교", "B3", "S19", 38), ("운곡교", "B7", "S19", 32), ("운곡교", "B10", "S19", 9),
("산외교", "B2", "H22", 31), ("산외교", "B5", "H22", 31),
("옥성교", "B9", "H19", 171), ("옥성교", "B10", "H19", 5), ("옥성교", "B11", "H19", 19), ("옥성교", "B12", "H19", 19)]
for b, m, d, n in rf:
dia = "H" + d[1:]
ev.append([b, m, d, "굽힘 반지름(C-1, 기초 철근)", n, "R %.2f" % OLD_R[dia], "R %.2f" % NEW_R[dia], None, "기초 철근 별도 확인 후 적용(사용자 규칙과 함께)"])
ev.append(["운곡교", "B9", "H16", "전단철근 갈고리", b9["stat"]["replaced"], "위 180° R20.4 / 연장 0 / 길이 2,144.7",
"위 180° R24 / 연장 100 / 길이 %.1f" % b9["length_new"][0], round((b9["length_new"][0] - 2144.7) * b9["stat"]["replaced"], 1),
"합계 길이 변화(mm). 갈고리 위쪽 피복 %.1f mm. 임시 값(설계자 확인 전)" % b9["min_cover_above_hook"]])
make_sheet("수정 증거(마크별)", "수정 증거 — 마크별 수정 전·후 값",
"본수·길이 변화는 실행 결과 JSON(c1_apply·c1_footing_*·c1_b9_ungok)에서 가져옴. 높이 z 는 기초 하단 기준 mm",
["교량", "마크", "직경", "항목", "본수", "수정 전", "수정 후", "길이·이동 변화 합계(mm)", "확인 방법·비고"],
ev, [10, 8, 8, 28, 8, 34, 34, 18, 52])
# ---------------------------------------------------------------- KDS 직경별 R
NOM = [("D13", 12.7, 2.0), ("D16", 15.9, 2.0), ("D19", 19.1, 3.5), ("D22", 22.2, 3.5), ("D25", 25.4, 3.5), ("D29", 28.6, 3.5), ("D32", 31.8, 3.5), ("D35", 34.9, 3.5)]
kr = []
for d, db, f in NOM:
inner_d = f * db
kr.append([d, db, "%.1fdb" % f if f != int(f) else "%ddb" % int(f), round(inner_d, 2), round(inner_d / 2, 2), round(inner_d / 2 + db / 2, 2),
"KDS 24 14 21 표 4.5-1(4.5.2.1): 이형철근 D16 이하 2db, D19 이상 3.5db. 최대값 규정 없음. 갈고리 연장 5db 이상(4.5.4.2)",
None, None, None])
r = len(kr)
for key in ("ungok", "sanoe", "okseong", "rampa"):
for d, x in kds[key]["per_dia"].items():
kr.append(["D" + d, None, None, None, None, x["req_center_R"], "모델 확인: " + BR[key] + " (최신 수정본)",
x["min_R_found"], x["arcs"], x["arcs_below"]])
make_sheet("KDS 직경별 R", "KDS 24 14 21 최소 굽힘 반지름 — 직경별 기준값과 4개교 모델 확인 결과",
"위 8행 = 기준값(공칭 직경). 아래 = 수정 후 모델 전수 스캔(중심선 호). 모델 기준 R 은 모델 파이프가 정수 직경이라 내면지름 ≥ 3.5×공칭이 되도록 올림한 값",
["직경", "공칭 db(mm)", "최소 내면지름 배수", "최소 내면지름(mm)", "최소 내면반지름(mm)", "최소 중심선 R(mm)", "출처·대상", "모델 최소 R", "호 개수", "기준 미달 호"],
kr, [8, 12, 14, 16, 16, 16, 60, 12, 10, 12])
# ---------------------------------------------------------------- 미수정·보류
hold = [
["운곡교", "P3 (H19 링)", "72본 / 호 144개", "굽힘 R 42.75 < 42.93", "호가 서로 이어진 형상이라 '호 반지름만 키우기' 방식으로 못 고침", "다른 방식 필요 (사용자 결정)", "R-1 보류"],
["옥성교", "C9·C13 (H25)", "18본 / 호 90개", "굽힘 R 56.25 < 56.95", "파이프 재생성 실패(형상 복잡)", "다른 방식 필요", "R-3 보류"],
["Ramp-A교", "C12 (H19)", "12본 / 호 60개", "굽힘 R 42.75 < 42.93", "파이프 재생성 실패(형상 복잡)", "다른 방식 필요", "R-4 보류"],
["운곡교", "B9 (H16)", "493본", "갈고리 R·연장이 도면에 없음(도면 오류)", "임시 수정(R24, 연장 100). 재료표 L 2,155 와 약 101mm 차이, 아래 90° 연장 72 < 5db 80", "설계자 확인", "R-8"],
["운곡교", "B2 (S25 U자)", "38본", "다리 끝을 B1 높이 2072.5 로 → 54.5mm 짧아짐", "산외·옥성은 다리 끝을 바깥 상면선(2400·2100)에 맞춤 — 해석 통일 필요", "사용자 결정(운곡교도 상면선 2100 으로 통일할지)", "R-5"],
["산외교", "B7 (H13 세로철근)", "98본", "양 끝 z 166 / 2384 가 주철근 사이에 놓임(바깥으로 걸리지 않음)", "운곡교 B9 와 같은 유형. 미수정", "설계자 확인", "R-6"],
["옥성교", "B12 (H19)", "19본", "도면 점보다 19mm 높음(엑셀 M-12)", "이번 기초 규칙과 별개 항목. 미수정", "사용자 결정", "R-7"],
["산외·옥성교", "기초 B 철근 전반", "-", "교축·교직 직경이 같아 이번에는 설계자 문의 없이 진행", "직경이 다른 교량이 나오면 계산서 확인 후 피복 작은 철근을 바깥으로 — 설계자 문의 사항 (OPEN #39)", "해당 시 문의", "규칙"],
["4개교", "엑셀 38건 중 위 항목 외", "-", "커플러·겹침 길이·+54 가산·개별 길이·조립용 철근 등", "수정 방향이 정해지지 않아(결정 칸 비어 있음) 미수정", "방향 결정 필요", "공통 문제 · 대안 시트"],
]
hf = {(i, 5): FILL_HOLD for i in range(len(hold))}
make_sheet("미수정·보류", "수정하지 않았거나 임시로 수정한 항목",
"사유와 필요한 결정을 같이 적음",
["교량", "마크", "대상", "문제", "사유·현재 상태", "필요한 결정", "연결"],
hold, [12, 20, 18, 44, 60, 30, 18], hf)
# ---------------------------------------------------------------- 수정 파일·해시
def sha(p):
h = hashlib.sha256()
with open(p, "rb") as f:
for blk in iter(lambda: f.read(1 << 20), b""):
h.update(blk)
return h.hexdigest()
files = [
("운곡교", "철근 모델랑 운곡교P1_바이브코딩/운곡교p1_수정_20261023.3dm", "C-1 굽힘 R(기초 제외) + 철근 레이어 켬", "중간본"),
("운곡교", "철근 모델랑 운곡교P1_바이브코딩/운곡교p1_수정2_20261023.3dm", "폐기된 규칙(같은 방향 철근 같은 높이)", "폐기"),
("운곡교", "철근 모델랑 운곡교P1_바이브코딩/운곡교p1_수정3_20261023.3dm", "기초 철근 높이 규칙 + 기초 R 보정", "중간본"),
("운곡교", "철근 모델랑 운곡교P1_바이브코딩/운곡교p1_수정4_20261026.3dm", "B9 R65·연장 150 시도", "폐기"),
("운곡교", "철근 모델랑 운곡교P1_바이브코딩/운곡교p1_수정5_20261026.3dm", "B9 R45·연장 100 시도", "폐기"),
("운곡교", "철근 모델랑 운곡교P1_바이브코딩/운곡교p1_수정6_20261026.3dm", "B9 R24(KDS)·연장 100 — 전체 수정 포함", "최신"),
("산외교", "검토_산외교P1/산외교P1 G5_수정_20261023.3dm", "C-1 굽힘 R(기초 제외)", "중간본"),
("산외교", "검토_산외교P1/산외교P1 G5_수정2_20261026.3dm", "기초 철근 규칙 + R 보정 — 전체 수정 포함", "최신"),
("옥성교", "검토_옥성교P1/옥성교P1_G5_수정_20261023.3dm", "C-1 굽힘 R(기초 제외)", "중간본"),
("옥성교", "검토_옥성교P1/옥성교P1_G5_수정2_20261026.3dm", "기초 철근 규칙 + R 보정 — 전체 수정 포함", "최신"),
("Ramp-A교", "Ramp-A교P1/ramp-A G5_수정_20261023.3dm", "C-1 굽힘 R — 전체 수정 포함(말뚝 기초라 기초 철근 해당 없음)", "최신"),
("운곡교", "철근 모델랑 운곡교P1_바이브코딩/운곡교p1_검토완료.3dm", "검토 당시 모델 사본(비교용)", "원본 사본"),
("산외교", "검토_산외교P1/산외교P1 G5_검토완료.3dm", "검토 당시 모델 사본(비교용)", "원본 사본"),
("옥성교", "검토_옥성교P1/옥성교P1_G5_검토완료.3dm", "검토 당시 모델 사본(비교용)", "원본 사본"),
("Ramp-A교", "Ramp-A교P1/ramp-A G5_검토완료.3dm", "검토 당시 모델 사본(비교용)", "원본 사본"),
]
fr = []
ff = {}
for i, (b, rel, what, st) in enumerate(files):
p = REV / rel
if p.exists():
stt = p.stat()
fr.append([b, "검토파일/" + rel, what, st, round(stt.st_size / 1e6, 1),
datetime.datetime.fromtimestamp(stt.st_mtime).strftime("%Y-%m-%d %H:%M"), sha(p)])
else:
fr.append([b, "검토파일/" + rel, what, st, None, None, "파일 없음"])
ff[(i, 3)] = FILL_OK if st == "최신" else (FILL_WARN if st == "폐기" else None)
ff = {k: v for k, v in ff.items() if v}
make_sheet("수정 파일·해시", "수정 결과 모델 파일 목록과 SHA-256 (증거용)",
"해시는 이 엑셀을 만든 시점(2026-10-26)의 파일 기준. 파일이 바뀌면 해시가 달라짐. 최신 = 모든 수정이 들어 있는 파일",
["교량", "경로(Pier_T 기준)", "내용", "상태", "크기(MB)", "저장 시각", "SHA-256"],
fr, [10, 64, 44, 10, 10, 18, 66], ff)
# ---------------------------------------------------------------- M-14(B9) 행 갱신
NEW_NOTE = ("임시 수정 (2026-10-26): 도면 가공도에 갈고리 원 부분 R·연장이 없어(도면 오류) 설계자 확인 전까지 임시값으로 수정 — "
"위 180° 갈고리 R24(KDS H16 최소 23.85), 연장 100(임의). 재료표 L 2,155 와 약 101mm 차이, 아래 90° 연장 72 < 5db 80. "
"수정 파일: 운곡교p1_수정6_20261026.3dm. '수정 내역' 시트 R-8, OPEN #39")
for name in ("교량별 항목 합본", "개별 항목"):
ws = wb[name]
for row in ws.iter_rows(min_row=4):
if row[1].value == "M-14" and row[2].value == "B9":
if name == "교량별 항목 합본":
row[7].value = NEW_NOTE
row[8].value = "기준↔모델 (도면 오류, 임시 수정)"
else:
row[6].value = NEW_NOTE
row[5].value = "기준↔모델 (도면 오류, 임시 수정)"
# ---------------------------------------------------------------- 안내 시트
a = wb["안내"]
start = a.max_row + 1
desc = [("수정 내역", "4개교 모델 수정 요약 R-1~R-9 (수정 전·후 값, 근거, 검증, 결과 파일) — 2026-10-26 추가"),
("수정 증거(마크별)", "마크별 본수·수정 전후 값·길이 변화"),
("KDS 직경별 R", "KDS 24 14 21 직경별 최소 굽힘 반지름과 4개교 모델 전수 확인 결과"),
("미수정·보류", "수정하지 않았거나 임시로 수정한 항목, 사유, 필요한 결정"),
("수정 파일·해시", "수정 결과 모델 파일 목록과 SHA-256")]
for i, (s, t) in enumerate(desc):
for j, v in enumerate((s, t), 1):
c = a.cell(row=start + i, column=j, value=v)
src = a.cell(row=11, column=j)
c.font = copy.copy(src.font)
c.fill = copy.copy(src.fill)
c.border = copy.copy(src.border)
c.alignment = copy.copy(src.alignment)
wb.save(XLSX)
print("saved", XLSX, wb.sheetnames)
+133
View File
@@ -0,0 +1,133 @@
#! python3
# C-1 apply: replace bend radii < KDS minimum in 4 review models (footing marks B* excluded by user decision).
# Geometry is replaced in place (ids, names, user strings, layers kept); results are saved under NEW names.
import sys, os, json, math, shutil, collections, traceback
sys.path.insert(0, r"C:\Users\User\AppData\Local\PierApp\jobs\c1_work")
import c1_core
import Rhino
from c1_core import BASE, plan_curve, make_pipe, required_rc
DATE = "20261023"
MODELS = {
"ungok": (os.path.join(BASE, "철근 모델랑 운곡교P1_바이브코딩"), "운곡교p1.3dm", "운곡교p1_대조코드표식.3dm"),
"sanoe": (os.path.join(BASE, "검토_산외교P1"), "산외교P1 G5.3dm", "산외교P1 G5_대조코드표식.3dm"),
"okseong": (os.path.join(BASE, "검토_옥성교P1"), "옥성교P1_G5.3dm", "옥성교P1_G5_대조코드표식.3dm"),
"rampa": (os.path.join(BASE, "Ramp-A교P1"), "ramp-A G5.3dm", "ramp-A G5_대조코드표식.3dm"),
}
OUT = r"C:\Users\User\AppData\Local\PierApp\jobs\c1_work\c1_apply.json"
res = {}
def is_footing(mark, layer):
return ("기초" in layer) or (mark or "").upper().startswith("B")
def short_arcs_left(doc, lay, st):
"""Count short arcs per (footing?) in centreline curves of the document (post check)."""
cnt = collections.Counter()
for o in doc.Objects.GetObjectList(st):
g = o.Geometry
L = lay.get(o.Attributes.LayerIndex, "")
if isinstance(g, Rhino.Geometry.PolyCurve) and "중심선" in L:
dia = o.Attributes.GetUserString("dia")
req, d = required_rc(dia)
for i in range(g.SegmentCount):
s = g.SegmentCurve(i)
ok, arc = s.TryGetArc()
if ok and not s.IsLinear() and arc.Radius < req - 1e-6 and math.degrees(arc.Angle) < 179.0:
cnt["footing" if is_footing(o.Attributes.GetUserString("mark"), L) else "other"] += 1
return dict(cnt)
try:
for key, (folder, plain, reviewed) in MODELS.items():
r = {"folder": folder}
res[key] = r
# 1) reviewed model copy (same folder)
src = os.path.join(folder, reviewed)
dst = os.path.join(folder, reviewed.replace("_대조코드표식", "_검토완료"))
if os.path.exists(dst):
r["reviewed_copy"] = "exists: " + dst
else:
shutil.copy2(src, dst)
r["reviewed_copy"] = dst
# 2) modify plain model headless
doc = Rhino.RhinoDoc.OpenHeadless(os.path.join(folder, plain))
tol = doc.ModelAbsoluteTolerance
st = Rhino.DocObjects.ObjectEnumeratorSettings()
st.HiddenObjects = True
st.LockedObjects = True
st.NormalObjects = True
lay = {l.Index: l.FullPath for l in doc.Layers}
r["objects_before"] = doc.Objects.Count
r["short_before"] = short_arcs_left(doc, lay, st)
breps = collections.defaultdict(list)
curves = []
for o in doc.Objects.GetObjectList(st):
g = o.Geometry
L = lay.get(o.Attributes.LayerIndex, "")
if isinstance(g, Rhino.Geometry.Brep) and "철근" in L:
breps[o.Attributes.Name].append(o)
elif isinstance(g, Rhino.Geometry.Curve) and "중심선" in L:
curves.append(o)
stat = collections.Counter()
per_mark = collections.OrderedDict()
for o in curves:
a = o.Attributes
mark = a.GetUserString("mark")
dia = a.GetUserString("dia")
L = lay.get(a.LayerIndex, "")
c = o.Geometry
if not isinstance(c, Rhino.Geometry.PolyCurve):
continue
pc, info = plan_curve(c, dia)
if info["status"] == "unchanged":
continue
if is_footing(mark, L):
stat["held_footing"] += 1
continue
if info["status"] != "ok":
stat["skipped_complex"] += 1
continue
nb = breps.get(a.Name.replace("-RC-", "-R-"), [])
if len(nb) != 1:
stat["skipped_no_brep"] += 1
continue
req, d = required_rc(dia)
pipes = make_pipe(pc, d, tol)
if not pipes or len(pipes) != 1 or not pipes[0].IsSolid:
stat["skipped_pipe_fail"] += 1
continue
v_new = Rhino.Geometry.VolumeMassProperties.Compute(pipes[0]).Volume
if abs(v_new / (math.pi * (d / 2.0) ** 2 * pc.GetLength()) - 1.0) > 0.002:
stat["skipped_volume"] += 1
continue
dl = pc.GetLength() - c.GetLength()
old_id, brep_id = o.Id, nb[0].Id
okc = doc.Objects.Replace(old_id, pc)
okb = doc.Objects.Replace(brep_id, pipes[0])
if not (okc and okb):
stat["replace_failed"] += 1
continue
for oid in (old_id, brep_id):
ro = doc.Objects.FindId(oid)
at = ro.Attributes.Duplicate()
at.SetUserString("bend_r_fix", "C-1 KDS 24 14 21 Table 4.5-1, Rc %.2f mm, %s" % (req, DATE))
doc.Objects.ModifyAttributes(ro, at, True)
stat["replaced"] += 1
pm = per_mark.setdefault(mark + "/" + dia, [0, 0.0])
pm[0] += 1
pm[1] += dl
r["stat"] = dict(stat)
r["per_mark"] = {k: {"bars": v[0], "sum_dlen_mm": round(v[1], 3)} for k, v in per_mark.items()}
r["short_after"] = short_arcs_left(doc, lay, st)
r["objects_after"] = doc.Objects.Count
out_path = os.path.join(folder, os.path.splitext(plain)[0] + "_수정_" + DATE + ".3dm")
r["saved"] = bool(doc.WriteFile(out_path, Rhino.FileIO.FileWriteOptions()))
r["out"] = out_path
doc.Dispose()
json.dump(res, open(OUT, "w", encoding="utf-8"), ensure_ascii=False, indent=1)
except Exception:
res["error"] = traceback.format_exc()
res["done"] = True
json.dump(res, open(OUT, "w", encoding="utf-8"), ensure_ascii=False, indent=1)
@@ -0,0 +1,115 @@
#! python3
# Ungok B9 (H16 shear bar): top 180-degree hook -> centre-line radius 65 mm, straight extension c = 150 mm (assumed, drawing has none).
# Bottom 90-degree hook (b 96) and vertical leg (a 1995) are kept as in the drawing schedule.
# Source: ..._수정3_20261023.3dm -> saved as ..._수정4_20261026.3dm (new name, originals untouched)
import sys, os, json, math, collections, traceback
sys.path.insert(0, r"C:\Users\User\AppData\Local\PierApp\jobs\c1_work")
import c1_core
import Rhino
from Rhino.Geometry import Arc, ArcCurve, PolyCurve, Point3d, Vector3d, LineCurve
from c1_core import BASE, make_pipe
DATE_TXT = "2026-10-26"
R_HOOK = 24.0
C_EXT = 100.0
FOLDER = os.path.join(BASE, "철근 모델랑 운곡교P1_바이브코딩")
SRC = os.path.join(FOLDER, "운곡교p1_수정3_20261023.3dm")
DST = os.path.join(FOLDER, "운곡교p1_수정6_20261026.3dm")
OUT = r"C:\Users\User\AppData\Local\PierApp\jobs\c1_work\c1_b9_ungok.json"
res = {}
try:
doc = Rhino.RhinoDoc.OpenHeadless(SRC)
tol = doc.ModelAbsoluteTolerance
st = Rhino.DocObjects.ObjectEnumeratorSettings()
st.HiddenObjects = True
st.LockedObjects = True
st.NormalObjects = True
lay = {l.Index: l.FullPath for l in doc.Layers}
res["objects_before"] = doc.Objects.Count
foot = [o for o in doc.Objects.GetObjectList(st) if o.Attributes.Name == "P1-FT"][0].Geometry.GetBoundingBox(True)
breps = collections.defaultdict(list)
curves = []
for o in doc.Objects.GetObjectList(st):
g = o.Geometry
L = lay.get(o.Attributes.LayerIndex, "")
if isinstance(g, Rhino.Geometry.Brep) and "철근" in L:
breps[o.Attributes.Name].append(o)
elif isinstance(g, Rhino.Geometry.Curve) and "중심선" in L and o.Attributes.GetUserString("mark") == "B9" and o.Attributes.GetUserString("host") == "P1-FT":
curves.append(o)
stat = collections.Counter()
len_old = []
len_new = []
max_top = -1e12
for o in curves:
a = o.Attributes
c = o.Geometry
nb = breps.get(a.Name.replace("-RC-", "-R-"), [])
if len(nb) != 1 or not isinstance(c, PolyCurve) or c.SegmentCount != 4:
stat["unexpected_shape"] += 1
continue
segs = [c.SegmentCurve(i).DuplicateCurve() for i in range(4)]
last = segs[3]
ok, arc = last.TryGetArc()
if not ok or abs(math.degrees(arc.Angle) - 180.0) > 0.5:
stat["top_not_180"] += 1
continue
p0 = last.PointAtStart
p1o = last.PointAtEnd
d = p1o - p0
d.Z = 0.0
d.Unitize()
t = Vector3d(last.TangentAtStart)
t.Unitize()
p1 = p0 + d * (2.0 * R_HOOK)
new_arc = Arc(p0, t, p1)
if not new_arc.IsValid:
stat["arc_invalid"] += 1
continue
p2 = p1 + (-t) * C_EXT
pc = PolyCurve()
for s in segs[:3]:
pc.Append(s)
pc.Append(ArcCurve(new_arc))
pc.Append(LineCurve(p1, p2))
pipes = make_pipe(pc, 16, tol)
if not pipes or len(pipes) != 1 or not pipes[0].IsSolid:
stat["pipe_fail"] += 1
continue
vol = Rhino.Geometry.VolumeMassProperties.Compute(pipes[0]).Volume
if abs(vol / (math.pi * 64.0 * pc.GetLength()) - 1.0) > 0.002:
stat["volume_off"] += 1
continue
cid, bid = o.Id, nb[0].Id
if not (doc.Objects.Replace(cid, pc) and doc.Objects.Replace(bid, pipes[0])):
stat["replace_failed"] += 1
continue
for oid in (cid, bid):
ro = doc.Objects.FindId(oid)
at = ro.Attributes.Duplicate()
at.SetUserString("b9_hook_fix", "top 180 deg hook R%.0f (KDS 24 14 21 Table 4.5-1 minimum for H16), extension c %.0f (assumed: drawing has none), %s" % (R_HOOK, C_EXT, DATE_TXT))
doc.Objects.ModifyAttributes(ro, at, True)
len_old.append(c.GetLength())
len_new.append(pc.GetLength())
bb = pipes[0].GetBoundingBox(True)
max_top = max(max_top, bb.Max.Z)
stat["replaced"] += 1
res["stat"] = dict(stat)
if len_old:
res["length_old"] = [round(min(len_old), 2), round(max(len_old), 2)]
res["length_new"] = [round(min(len_new), 2), round(max(len_new), 2)]
res["total_len_old_m"] = round(sum(len_old) / 1000.0, 2)
res["total_len_new_m"] = round(sum(len_new) / 1000.0, 2)
res["pipe_top_z_rel"] = round(max_top - foot.Min.Z, 2)
res["footing_top_z_rel"] = round(foot.Max.Z - foot.Min.Z, 2)
res["min_cover_above_hook"] = round(foot.Max.Z - max_top, 2)
doc.Strings.SetString("수정일", DATE_TXT)
prev = doc.Strings.GetValue("수정내용") or ""
doc.Strings.SetString("수정내용", (prev + " | " if prev else "") + "B9 top hook R24 (KDS min for H16 23.85, rounded up like other H16 bends) + extension 100 (user 2026-10-26, replaces R65/R45 versions)")
res["objects_after"] = doc.Objects.Count
res["saved"] = bool(doc.WriteFile(DST, Rhino.FileIO.FileWriteOptions()))
res["out"] = DST
doc.Dispose()
except Exception:
res["error"] = traceback.format_exc()
res["done"] = True
json.dump(res, open(OUT, "w", encoding="utf-8"), ensure_ascii=False, indent=1)
@@ -0,0 +1,41 @@
#! python3
import os, json, math, collections, traceback
import Rhino
P = r"D:\★Pier 자료\프로그램\Pier_T\검토파일\철근 모델랑 운곡교P1_바이브코딩\운곡교p1_수정6_20261026.3dm"
OUT = r"C:\Users\User\AppData\Local\PierApp\jobs\c1_work\c1_b9_verify.json"
res = {}
try:
doc = Rhino.RhinoDoc.OpenHeadless(P)
st = Rhino.DocObjects.ObjectEnumeratorSettings()
st.HiddenObjects = True; st.LockedObjects = True; st.NormalObjects = True
lay = {l.Index: l for l in doc.Layers}
cnt = collections.Counter(); radii = collections.Counter(); tails = collections.Counter(); lens = collections.Counter()
vis = collections.Counter()
for o in doc.Objects.GetObjectList(st):
a = o.Attributes
if a.GetUserString("mark") != "B9":
continue
g = o.Geometry
L = lay[a.LayerIndex]
vis[(L.FullPath, "layer_on" if L.IsVisible else "layer_off")] += 1
cnt["fix_attr" if a.GetUserString("b9_hook_fix") else "no_fix_attr"] += 1
if isinstance(g, Rhino.Geometry.PolyCurve):
cnt["curve"] += 1
segs = [g.SegmentCurve(i) for i in range(g.SegmentCount)]
lens[round(g.GetLength(), 1)] += 1
arcs = []
for s in segs:
ok, arc = s.TryGetArc()
if ok and not s.IsLinear():
arcs.append((round(arc.Radius, 2), round(math.degrees(arc.Angle), 1)))
radii[str(arcs)] += 1
tails[str(round(segs[-1].GetLength(), 1)) + " nseg=" + str(len(segs))] += 1
res = {"counts": dict(cnt), "arcs": dict(radii), "last_segment": dict(tails), "lengths": dict(lens),
"layers": {k[0] + "|" + k[1]: v for k, v in vis.items()}, "strings": {"수정일": doc.Strings.GetValue("수정일"), "수정내용": doc.Strings.GetValue("수정내용")},
"objects": doc.Objects.Count}
doc.Dispose()
except Exception:
res["error"] = traceback.format_exc()
res["done"] = True
json.dump(res, open(OUT, "w", encoding="utf-8"), ensure_ascii=False, indent=1)
@@ -0,0 +1,70 @@
#! python3
# capture Front / Right viewport images of the footing rebar of a modified model + projected pixel positions of reference heights.
# config: cap_cfg.json next to this script: {"key": ..., "out": dir, "zlines": [[label, z_rel], ...]}
import os, json, traceback
import Rhino
import Rhino.Geometry as rg
import System
import System.Drawing
HERE = os.path.dirname(os.path.abspath(__file__))
cfg = json.load(open(os.path.join(HERE, "cap_cfg.json"), encoding="utf-8"))
res = {"key": cfg["key"]}
try:
doc = Rhino.RhinoDoc.ActiveDoc
res["doc"] = doc.Path
# layers: footing concrete + footing rebar only
for l in doc.Layers:
if l.IsDeleted:
continue
p = l.FullPath
show = p.startswith("P1::철근::기초") or p == "P1" or p == "P1::철근" # footing concrete hidden so the rebar is visible
doc.Layers.ForceLayerVisible(l.Index) if show else None
if not show:
l.IsVisible = False
st = Rhino.DocObjects.ObjectEnumeratorSettings()
st.HiddenObjects = True; st.LockedObjects = True; st.NormalObjects = True
foot = [o for o in doc.Objects.GetObjectList(st) if o.Attributes.Name == "P1-FT"][0]
for o in doc.Objects.GetObjectList(st): # make sure footing objects themselves are shown
L = doc.Layers[o.Attributes.LayerIndex].FullPath
if L.startswith("P1::철근::기초"):
doc.Objects.Show(o, True)
fb = foot.Geometry.GetBoundingBox(True)
res["footing_bbox"] = [fb.Min.X, fb.Min.Y, fb.Min.Z, fb.Max.X, fb.Max.Y, fb.Max.Z]
view = doc.Views.ActiveView
out = {}
for name, proj in (("Front", Rhino.Display.DefinedViewportProjection.Front), ("Right", Rhino.Display.DefinedViewportProjection.Right)):
vp = view.ActiveViewport
vp.SetProjection(proj, name, False)
vp.DisplayMode = Rhino.Display.DisplayModeDescription.FindByName("Shaded") or vp.DisplayMode
bb = rg.BoundingBox(fb.Min, fb.Max)
bb.Inflate(300.0)
vp.ZoomBoundingBox(bb)
view.Redraw()
Rhino.RhinoApp.Wait()
cw, ch = vp.Size.Width, vp.Size.Height
W = 1800
H = int(round(W * ch / float(cw)))
sc = W / float(cw)
bmp = view.CaptureToBitmap(System.Drawing.Size(W, H))
png = os.path.join(cfg["out"], "%s_%s.png" % (cfg["key"], name))
bmp.Save(png, System.Drawing.Imaging.ImageFormat.Png)
info = {"png": png, "size": [bmp.Width, bmp.Height], "client": [cw, ch], "scale": sc, "lines": {}}
zb = fb.Min.Z
for label, zrel in cfg["zlines"]:
if name == "Front":
a, b = rg.Point3d(fb.Min.X, 0, zb + zrel), rg.Point3d(fb.Max.X, 0, zb + zrel)
else:
a, b = rg.Point3d(0, fb.Min.Y, zb + zrel), rg.Point3d(0, fb.Max.Y, zb + zrel)
pa, pb = vp.WorldToClient(a), vp.WorldToClient(b)
info["lines"][label] = [[pa.X * sc, pa.Y * sc], [pb.X * sc, pb.Y * sc]]
out[name] = info
res["views"] = out
except Exception:
res["error"] = traceback.format_exc()
res["done"] = True
json.dump(res, open(os.path.join(cfg["out"], "%s_capture.json" % cfg["key"]), "w", encoding="utf-8"), ensure_ascii=False, indent=1)
try:
Rhino.RhinoDoc.ActiveDoc.Modified = False
except Exception:
pass
+102
View File
@@ -0,0 +1,102 @@
#! python3
# shared logic for C-1 (bend radius -> KDS 24 14 21 Table 4.5-1). Pure geometry, no document edits.
import math
import Rhino
from Rhino.Geometry import Arc, Line, Point3d, Vector3d, PolyCurve, PolylineCurve, ArcCurve, Curve, Brep, PipeCapMode
from Rhino.Geometry.Intersect import Intersection
BASE = r"D:\★Pier 자료\프로그램\Pier_T\검토파일"
NOMINAL = {13: 12.7, 16: 15.9, 19: 19.1, 22: 22.2, 25: 25.4, 29: 28.6, 32: 31.8, 35: 34.9}
def required_rc(dia):
"""Minimum centreline bend radius: inner diameter >= 3.5db (D19+) / 2db (<=D16), db nominal, tube d = integer dia."""
d = int("".join(ch for ch in dia if ch.isdigit()))
nom = NOMINAL[d]
inner_r = 1.75 * nom if d >= 19 else 1.0 * nom
return math.ceil((inner_r + d / 2.0) * 100.0) / 100.0, d
def _is_straight(c):
if isinstance(c, PolylineCurve):
return True
return c.IsLinear(1e-6)
def plan_curve(poly, dia):
"""Return (new_polycurve or None, info). info['short'] = number of short arcs, info['status'] ok|complex|unchanged."""
req, d = required_rc(dia)
n = poly.SegmentCount
segs = [poly.SegmentCurve(i).DuplicateCurve() for i in range(n)]
short = []
for i, s in enumerate(segs):
ok, arc = s.TryGetArc()
if ok and not s.IsLinear() and arc.Radius < req - 1e-6 and math.degrees(arc.Angle) < 179.0:
short.append(i)
info = {"short": len(short), "req": req, "status": "unchanged"}
if not short:
return None, info
# each short arc needs straight neighbours (or curve ends) and tangent continuity
for i in short:
for j in (i - 1, i + 1):
if 0 <= j < n and not _is_straight(segs[j]):
info["status"] = "complex"
return None, info
if 0 <= j < n and j in short:
info["status"] = "complex"
return None, info
new = list(segs)
for i in short:
ok, arc = segs[i].TryGetArc()
p0, p1 = arc.StartPoint, arc.EndPoint
t0 = segs[i].TangentAtStart
t1 = segs[i].TangentAtEnd
t0.Unitize()
t1.Unitize()
ok2, a, b = Intersection.LineLine(Line(p0, p0 + t0 * 1e5), Line(p1 - t1 * 1e5, p1))
if not ok2:
info["status"] = "complex"
return None, info
corner = Line(p0, p0 + t0 * 1e5).PointAt(a)
theta = math.acos(max(-1.0, min(1.0, t0 * t1)))
tl = req * math.tan(theta / 2.0)
ns = corner - t0 * tl
ne = corner + t1 * tl
mid_arc = Arc(ns, t0, ne)
if not mid_arc.IsValid:
info["status"] = "complex"
return None, info
new[i] = ArcCurve(mid_arc)
if i - 1 >= 0:
pc = new[i - 1].DuplicateCurve()
new[i - 1] = _retarget(pc, end=ns)
if i + 1 < n:
nc = new[i + 1].DuplicateCurve()
new[i + 1] = _retarget(nc, start=ne)
pc = PolyCurve()
for s in new:
if s is None:
info["status"] = "complex"
return None, info
pc.Append(s)
info["status"] = "ok"
return pc, info
def _retarget(c, start=None, end=None):
if isinstance(c, PolylineCurve):
pts = [c.Point(i) for i in range(c.PointCount)]
if start is not None:
pts[0] = start
if end is not None:
pts[-1] = end
return PolylineCurve(pts)
a = start if start is not None else c.PointAtStart
b = end if end is not None else c.PointAtEnd
return Rhino.Geometry.LineCurve(a, b)
def make_pipe(curve, d, tol):
r = d / 2.0
res = Brep.CreatePipe(curve, r, False, PipeCapMode.Flat, True, tol, Rhino.RhinoMath.ToRadians(1.0))
return res
@@ -0,0 +1,66 @@
#! python3
# read-only diagnosis of the 102 bars the corner method could not fix: segment structure and whether CreatePipe works on the ORIGINAL curve
import os, json, math, collections, traceback, sys
sys.path.insert(0, r"C:\Users\User\AppData\Local\PierApp\jobs\c1_work")
import Rhino
from Rhino.Geometry import PipeCapMode, Brep
from c1_core import BASE, plan_curve, required_rc
TARGETS = {
"ungok": (os.path.join(BASE, "철근 모델랑 운곡교P1_바이브코딩", "운곡교p1_수정6_20261026.3dm"), ["P3"]),
"okseong": (os.path.join(BASE, "검토_옥성교P1", "옥성교P1_G5_수정2_20261026.3dm"), ["C9", "C13"]),
"rampa": (os.path.join(BASE, "Ramp-A교P1", "ramp-A G5_수정_20261023.3dm"), ["C12"]),
}
OUT = r"C:\Users\User\AppData\Local\PierApp\jobs\c1_work\c1_diag_complex.json"
res = {}
try:
for key, (p, marks) in TARGETS.items():
doc = Rhino.RhinoDoc.OpenHeadless(p)
tol = doc.ModelAbsoluteTolerance
st = Rhino.DocObjects.ObjectEnumeratorSettings()
st.HiddenObjects = True; st.LockedObjects = True; st.NormalObjects = True
lay = {l.Index: l.FullPath for l in doc.Layers}
out = {}
for o in doc.Objects.GetObjectList(st):
g = o.Geometry
if not (isinstance(g, Rhino.Geometry.PolyCurve) and "중심선" in lay.get(o.Attributes.LayerIndex, "")):
continue
a = o.Attributes
m = a.GetUserString("mark")
if m not in marks:
continue
dia = a.GetUserString("dia")
req, d = required_rc(dia)
pc, info = plan_curve(g, dia)
if info["status"] == "unchanged":
continue
rec = out.setdefault(m, {"bars": 0, "plan_status": collections.Counter(), "orig_pipe_ok": 0, "orig_pipe_fail": 0, "new_pipe_ok": 0, "new_pipe_fail": 0, "sample": None})
rec["bars"] += 1
rec["plan_status"][info["status"]] += 1
r0 = Brep.CreatePipe(g, d / 2.0, False, PipeCapMode.Flat, True, tol, Rhino.RhinoMath.ToRadians(1.0))
if r0 and len(r0) == 1 and r0[0].IsSolid:
rec["orig_pipe_ok"] += 1
else:
rec["orig_pipe_fail"] += 1
if pc is not None:
r1 = Brep.CreatePipe(pc, d / 2.0, False, PipeCapMode.Flat, True, tol, Rhino.RhinoMath.ToRadians(1.0))
if r1 and len(r1) == 1 and r1[0].IsSolid:
rec["new_pipe_ok"] += 1
else:
rec["new_pipe_fail"] += 1
if rec["sample"] is None or (rec["orig_pipe_fail"] == 1 and rec["sample"].get("flag") != "fail"):
segs = []
for i in range(g.SegmentCount):
s = g.SegmentCurve(i)
ok, arc = s.TryGetArc()
segs.append([type(s).__name__, round(s.GetLength(), 2), round(arc.Radius, 2) if ok and not s.IsLinear() else None,
round(math.degrees(arc.Angle), 2) if ok and not s.IsLinear() else None])
rec["sample"] = {"name": a.Name, "flag": "fail" if rec["orig_pipe_fail"] else "ok", "valid": g.IsValid, "segs": segs}
for m in out.values():
m["plan_status"] = dict(m["plan_status"])
res[key] = out
doc.Dispose()
except Exception:
res["error"] = traceback.format_exc()
res["done"] = True
json.dump(res, open(OUT, "w", encoding="utf-8"), ensure_ascii=False, indent=1)
+79
View File
@@ -0,0 +1,79 @@
#! python3
# C-1 dry run: plan new centrelines + pipes for the 4 review models, no document edits.
import sys, os, json, math, collections, traceback
sys.path.insert(0, r"C:\Users\User\AppData\Local\PierApp\jobs\c1_work")
import importlib
import c1_core
importlib.reload(c1_core)
import Rhino
from c1_core import BASE, plan_curve, make_pipe, required_rc
MODELS = {
"ungok": os.path.join(BASE, "철근 모델랑 운곡교P1_바이브코딩", "운곡교p1.3dm"),
"sanoe": os.path.join(BASE, "검토_산외교P1", "산외교P1 G5.3dm"),
"okseong": os.path.join(BASE, "검토_옥성교P1", "옥성교P1_G5.3dm"),
"rampa": os.path.join(BASE, "Ramp-A교P1", "ramp-A G5.3dm"),
}
OUT = r"C:\Users\User\AppData\Local\PierApp\jobs\c1_work\c1_dry.json"
res = {}
try:
for key, path in MODELS.items():
doc = Rhino.RhinoDoc.OpenHeadless(path)
tol = doc.ModelAbsoluteTolerance
st = Rhino.DocObjects.ObjectEnumeratorSettings()
st.HiddenObjects = True
st.LockedObjects = True
st.NormalObjects = True
lay = {l.Index: l.FullPath for l in doc.Layers}
breps = {}
curves = []
for o in doc.Objects.GetObjectList(st):
g = o.Geometry
if isinstance(g, Rhino.Geometry.Brep) and "철근" in lay.get(o.Attributes.LayerIndex, ""):
breps.setdefault(o.Attributes.Name, []).append(o)
elif isinstance(g, Rhino.Geometry.Curve) and "중심선" in lay.get(o.Attributes.LayerIndex, ""):
curves.append(o)
per = collections.OrderedDict()
for o in curves:
a = o.Attributes
mark = a.GetUserString("mark")
dia = a.GetUserString("dia")
m = per.setdefault((mark, dia), collections.Counter())
m["bars"] += 1
c = o.Geometry
if not isinstance(c, Rhino.Geometry.PolyCurve):
m["not_poly"] += 1
continue
pc, info = plan_curve(c, dia)
if info["status"] == "unchanged":
continue
m["short_bars"] += 1
m["short_arcs"] += info["short"]
if info["status"] != "ok":
m["complex"] += 1
continue
req, d = required_rc(dia)
nb = breps.get(a.Name.replace("-RC-", "-R-"), [])
if len(nb) != 1:
m["brep_match_" + str(len(nb))] += 1
continue
pipes = make_pipe(pc, d, tol)
if not pipes or len(pipes) != 1 or not pipes[0].IsSolid:
m["pipe_fail"] += 1
continue
v_new = Rhino.Geometry.VolumeMassProperties.Compute(pipes[0]).Volume
v_exp = math.pi * (d / 2.0) ** 2 * pc.GetLength()
if abs(v_new / v_exp - 1.0) > 0.002:
m["vol_off"] += 1
dl = pc.GetLength() - c.GetLength()
m["ok"] += 1
m["sum_dlen_x1000"] += int(round(dl * 1000))
if abs(dl) > m["max_dlen_x1000"]:
m["max_dlen_x1000"] = int(round(abs(dl) * 1000))
if pc.PointAtStart.DistanceTo(c.PointAtStart) > 1e-6 or pc.PointAtEnd.DistanceTo(c.PointAtEnd) > 1e-6:
m["end_moved"] += 1
res[key] = {"objects": doc.Objects.Count, "marks": [{"mark": k[0], "dia": k[1], "req": required_rc(k[1])[0], **dict(v)} for k, v in per.items() if v.get("short_bars")]}
doc.Dispose()
except Exception:
res["error"] = traceback.format_exc()
json.dump(res, open(OUT, "w", encoding="utf-8"), ensure_ascii=False, indent=1)
@@ -0,0 +1,38 @@
#! python3
import os, json, traceback, collections, math
import Rhino
import Rhino.Geometry as rg
B = r"D:\★Pier 자료\프로그램\Pier_T\검토파일"
M = {"운곡": B + r"\철근 모델랑 운곡교P1_바이브코딩\운곡교p1_수정7_20261026.3dm",
"산외": B + r"\검토_산외교P1\산외교P1 G5_수정5_20261027.3dm",
"옥성": B + r"\검토_옥성교P1\옥성교P1_G5_수정6_20261026.3dm",
"RampA": B + r"\Ramp-A교P1\ramp-A G5_수정6_20261026.3dm"}
res = {}
try:
for k, p in M.items():
doc = Rhino.RhinoDoc.OpenHeadless(p)
st = Rhino.DocObjects.ObjectEnumeratorSettings(); st.HiddenObjects = True; st.LockedObjects = True; st.NormalObjects = True
lay = {l.Index: l.FullPath for l in doc.Layers}
d = collections.defaultdict(list)
for o in doc.Objects.GetObjectList(st):
g = o.Geometry
if isinstance(g, rg.Curve) and "중심선" in lay.get(o.Attributes.LayerIndex, ""):
m = o.Attributes.GetUserString("mark")
if m in ("B1", "B2", "B3", "B4", "B5", "B6"):
d[m].append((o, g))
out = {}
for m, lst in sorted(d.items()):
o, g = lst[len(lst)//2]
segs = []
if isinstance(g, rg.PolyCurve):
for i in range(g.SegmentCount):
s = g.SegmentCurve(i)
segs.append(("L" if s.IsLinear() else "A", round(s.GetLength(), 1), [round(x) for x in (s.PointAtStart.X, s.PointAtStart.Y, s.PointAtStart.Z)], [round(x) for x in (s.PointAtEnd.X, s.PointAtEnd.Y, s.PointAtEnd.Z)]))
else:
segs.append((type(g).__name__, round(g.GetLength(), 1), [round(x) for x in (g.PointAtStart.X, g.PointAtStart.Y, g.PointAtStart.Z)], [round(x) for x in (g.PointAtEnd.X, g.PointAtEnd.Y, g.PointAtEnd.Z)]))
out[m] = {"n": len(lst), "name": o.Attributes.Name, "dia": o.Attributes.GetUserString("dia"), "shape": o.Attributes.GetUserString("shape"), "design_length": o.Attributes.GetUserString("design_length"), "len": round(g.GetLength(), 1), "segs": segs}
res[k] = out
doc.Dispose()
except Exception:
res["error"] = traceback.format_exc()
json.dump(res, open(r"C:\Users\User\AppData\Local\PierApp\jobs\c1_work\c1_dump_b1b4.json", "w", encoding="utf-8"), ensure_ascii=False, indent=1)
@@ -0,0 +1,188 @@
#! python3
# A: finish the C-1 bars the corner method could not do (Ungok P3 72, Okseong C9/C13 18, Ramp-A C12 12)
# C: Ungok B2 leg ends 2072.5 -> 2100 (outer top line, same reading as Sanoe / Okseong)
# Sources: Ungok ..._수정6 -> ..._수정7_20261026 ; Okseong ..._수정2 -> ..._수정4_20261026 ; Ramp-A ..._수정_20261023 -> ..._수정2_20261026
import sys, os, json, math, collections, traceback
sys.path.insert(0, r"C:\Users\User\AppData\Local\PierApp\jobs\c1_work")
import c1_core
import Rhino
from Rhino.Geometry import Transform, Vector3d, PolyCurve, Point3d, PipeCapMode, Brep
from c1_core import BASE, plan_curve, required_rc, _retarget
DATE_TXT = "2026-10-26"
OUT = r"C:\Users\User\AppData\Local\PierApp\jobs\c1_work\c1_fix_remaining.json"
JOBS = {
"ungok": {"src": os.path.join(BASE, "철근 모델랑 운곡교P1_바이브코딩", "운곡교p1_수정6_20261026.3dm"),
"dst": os.path.join(BASE, "철근 모델랑 운곡교P1_바이브코딩", "운곡교p1_수정7_20261026.3dm"),
"marks": {"P3": "scale"}, "b2": True,
"note": "C-1 finish: P3 hook arcs R42.93 (sequential scale); footing B2 leg ends 2100"},
"okseong": {"src": os.path.join(BASE, "검토_옥성교P1", "옥성교P1_G5_수정2_20261026.3dm"),
"dst": os.path.join(BASE, "검토_옥성교P1", "옥성교P1_G5_수정4_20261026.3dm"),
"marks": {"C9": "corner", "C13": "corner"}, "b2": False,
"note": "C-1 finish: C9, C13 (H25) R56.95 with robust pipe settings"},
"rampa": {"src": os.path.join(BASE, "Ramp-A교P1", "ramp-A G5_수정_20261023.3dm"),
"dst": os.path.join(BASE, "Ramp-A교P1", "ramp-A G5_수정2_20261026.3dm"),
"marks": {"C12": "corner"}, "b2": False,
"note": "C-1 finish: C12 (H19) R42.93 with robust pipe settings"},
}
res = {}
def robust_pipe(curve, d, tol):
"""first variant that gives one closed solid whose volume matches pi r^2 L within 0.5 %"""
for fit, atol in ((True, tol), (False, tol), (True, 0.01), (True, 0.1)):
rr = Brep.CreatePipe(curve, d / 2.0, False, PipeCapMode.Flat, fit, atol, Rhino.RhinoMath.ToRadians(1.0))
if rr and len(rr) == 1 and rr[0].IsSolid:
vol = Rhino.Geometry.VolumeMassProperties.Compute(rr[0]).Volume
if abs(vol / (math.pi * (d / 2.0) ** 2 * curve.GetLength()) - 1.0) <= 0.005:
return rr[0], "fit=%s atol=%g" % (fit, atol)
return None, None
def scale_chain(c, req):
"""arcs below req are scaled about their start point; everything after is translated, so start point and start tangent are kept"""
n = c.SegmentCount
off = Vector3d(0, 0, 0)
pc = PolyCurve()
changed = 0
for i in range(n):
s = c.SegmentCurve(i).DuplicateCurve()
ok, arc = s.TryGetArc()
S, E = s.PointAtStart, s.PointAtEnd
if ok and not s.IsLinear() and arc.Radius < req - 1e-6:
k = req / arc.Radius
s.Transform(Transform.Scale(S, k))
s.Transform(Transform.Translation(off))
off = off + (E - S) * (k - 1.0)
changed += 1
else:
s.Transform(Transform.Translation(off))
pc.Append(s)
return (pc if changed else None), off.Length, changed
def short_left(doc, lay, st):
cnt = collections.Counter()
for o in doc.Objects.GetObjectList(st):
g = o.Geometry
if isinstance(g, PolyCurve) and "중심선" in lay.get(o.Attributes.LayerIndex, ""):
req, d = required_rc(o.Attributes.GetUserString("dia"))
for i in range(g.SegmentCount):
s = g.SegmentCurve(i)
ok, arc = s.TryGetArc()
if ok and not s.IsLinear() and arc.Radius < req - 1e-6:
cnt[o.Attributes.GetUserString("mark")] += 1
return dict(cnt)
def run_one(key, job):
r = {}
doc = Rhino.RhinoDoc.OpenHeadless(job["src"])
tol = doc.ModelAbsoluteTolerance
st = Rhino.DocObjects.ObjectEnumeratorSettings()
st.HiddenObjects = True; st.LockedObjects = True; st.NormalObjects = True
lay = {l.Index: l.FullPath for l in doc.Layers}
r["objects_before"] = doc.Objects.Count
r["short_before"] = short_left(doc, lay, st)
ft = [o for o in doc.Objects.GetObjectList(st) if o.Attributes.Name == "P1-FT"]
fbot = ft[0].Geometry.GetBoundingBox(True).Min.Z if ft else 0.0 # pile foundation (Ramp-A) has no footing solid
breps = collections.defaultdict(list)
curves = []
for o in doc.Objects.GetObjectList(st):
g = o.Geometry
L = lay.get(o.Attributes.LayerIndex, "")
if isinstance(g, Brep) and "철근" in L:
breps[o.Attributes.Name].append(o)
elif isinstance(g, Rhino.Geometry.Curve) and "중심선" in L:
curves.append(o)
stat = collections.Counter()
drift = []
pipe_how = collections.Counter()
for o in curves:
a = o.Attributes
m = a.GetUserString("mark")
mode = job["marks"].get(m)
isb2 = job["b2"] and m == "B2" and a.GetUserString("host") == "P1-FT"
if not mode and not isb2:
continue
dia = a.GetUserString("dia")
req, d = required_rc(dia)
c = o.Geometry
nb = breps.get(a.Name.replace("-RC-", "-R-"), [])
if len(nb) != 1 or not isinstance(c, PolyCurve):
stat[m + "_unexpected"] += 1
continue
did = []
newc = c.Duplicate()
if isb2:
tz = fbot + 2100.0
n = newc.SegmentCount
s0, sN = newc.SegmentCurve(0), newc.SegmentCurve(n - 1)
if abs(s0.TangentAtStart.Z) < 0.999 or abs(sN.TangentAtEnd.Z) < 0.999 or abs(s0.PointAtStart.Z - (fbot + 2072.5)) > 0.6 or abs(sN.PointAtEnd.Z - (fbot + 2072.5)) > 0.6:
stat["B2_unexpected_ends"] += 1
continue
segs = [newc.SegmentCurve(i).DuplicateCurve() for i in range(n)]
p0, pN = segs[0].PointAtStart, segs[-1].PointAtEnd
segs[0] = _retarget(segs[0], start=Point3d(p0.X, p0.Y, tz))
segs[-1] = _retarget(segs[-1], end=Point3d(pN.X, pN.Y, tz))
newc = PolyCurve()
for s in segs:
newc.Append(s)
did.append("legs end z 2100")
elif mode == "scale":
pc, dist, k = scale_chain(newc, req)
if pc is None:
stat[m + "_nothing_to_do"] += 1
continue
drift.append(dist)
newc = pc
did.append("R %.2f (scale chain, end shift %.2f mm)" % (req, dist))
else:
pc, info = plan_curve(newc, dia)
if info["status"] != "ok":
stat[m + "_plan_" + info["status"]] += 1
continue
newc = pc
did.append("R %.2f" % req)
pipe, how = robust_pipe(newc, d, tol)
if pipe is None:
stat[m + "_pipe_fail"] += 1
continue
pipe_how[how] += 1
cid, bid = o.Id, nb[0].Id
if not (doc.Objects.Replace(cid, newc) and doc.Objects.Replace(bid, pipe)):
stat[m + "_replace_failed"] += 1
continue
for oid in (cid, bid):
ro = doc.Objects.FindId(oid)
at = ro.Attributes.Duplicate()
key_ = "footing_fix" if isb2 else "bend_r_fix"
old = at.GetUserString(key_) or ""
at.SetUserString(key_, (old + " | " if old else "") + "; ".join(did) + " (" + DATE_TXT + ")")
doc.Objects.ModifyAttributes(ro, at, True)
stat[("B2" if isb2 else m) + "_done"] += 1
r["stat"] = dict(stat)
r["pipe_settings"] = dict(pipe_how)
if drift:
r["end_shift_mm"] = {"max": round(max(drift), 2), "mean": round(sum(drift) / len(drift), 2)}
r["short_after"] = short_left(doc, lay, st)
doc.Strings.SetString("수정일", DATE_TXT)
prev = doc.Strings.GetValue("수정내용") or ""
doc.Strings.SetString("수정내용", (prev + " | " if prev else "") + job["note"])
r["objects_after"] = doc.Objects.Count
r["saved"] = bool(doc.WriteFile(job["dst"], Rhino.FileIO.FileWriteOptions()))
r["out"] = job["dst"]
doc.Dispose()
return r
for key, job in JOBS.items():
if os.path.exists(job["dst"]): # already produced by an earlier run: keep it
continue
try:
res[key] = run_one(key, job)
except Exception:
res[key] = {"error": traceback.format_exc()}
json.dump(res, open(OUT, "w", encoding="utf-8"), ensure_ascii=False, indent=1)
res["done"] = True
json.dump(res, open(OUT, "w", encoding="utf-8"), ensure_ascii=False, indent=1)
@@ -0,0 +1,172 @@
#! python3
# Footing rebar of Sanoe and Okseong under the user rule (2026-10-23/26): outermost bars on the drawing lines
# (top: centre 100 below top, bottom: centre 150 above bottom), inner bars touch them (sum of radii), U legs end on the outer
# top line (drawing leg length = line to line). Equal bar diameters in both directions in both bridges -> no designer query.
# plus C-1 bend radius for the listed footing marks. Results are saved under NEW names (..._수정2_20261023.3dm).
import sys, os, json, math, collections, traceback
sys.path.insert(0, r"C:\Users\User\AppData\Local\PierApp\jobs\c1_work")
import c1_core
import Rhino
from Rhino.Geometry import Transform, Vector3d, PolyCurve, Point3d
from c1_core import BASE, plan_curve, make_pipe, required_rc, _retarget
DATE_TXT = "2026-10-26"
OUT = r"C:\Users\User\AppData\Local\PierApp\jobs\c1_work\c1_footing_other.json"
# per mark: dz, expected z range before (rel. footing bottom), end_z (U leg tip, None = keep after translation)
JOBS = {
"sanoe": {
"src": os.path.join(BASE, "검토_산외교P1", "산외교P1 G5_수정_20261023.3dm"),
"dst": os.path.join(BASE, "검토_산외교P1", "산외교P1 G5_수정2_20261023.3dm"),
"plan": {
"B1": (-22.5, (2422.5, 2422.5), None),
"B4": (6.5, (2377.5, 2377.5), None),
"B3": (22.5, (127.5, 127.5), None),
"B2": (22.5, (127.5, 2377.5), 2400.0),
"B6": (-0.5, (172.5, 172.5), None),
"B5": (-0.5, (172.5, 2422.5), 2400.0),
},
"rfix": {"B2", "B5"},
"note": "footing: B1 z2400, B4 z2384, B3/B2 z150 (B2 legs end 2400), B6/B5 z172 (B5 legs end 2400); C-1 R for B2,B5",
},
"okseong": {
"src": os.path.join(BASE, "검토_옥성교P1", "옥성교P1_G5_수정_20261023.3dm"),
"dst": os.path.join(BASE, "검토_옥성교P1", "옥성교P1_G5_수정2_20261023.3dm"),
"plan": {
"B5": (-6.5, (1102.5, 2077.5), None),
"B7": (-6.5, (1102.5, 2077.5), None),
"B6": (6.5, (172.5, 2122.5), 2100.0),
"B8": (6.5, (172.5, 2122.5), 2100.0),
},
"rfix": {"B9", "B10", "B11", "B12"},
"note": "footing: B5/B7 z2071, B6/B8 z179 (legs end 2100), B1-B4 unchanged on lines 2100/150; C-1 R for B9-B12",
},
}
res = {}
def zr(g):
b = g.GetBoundingBox(True)
return b.Min.Z, b.Max.Z
def run_one(key, job):
r = {}
doc = Rhino.RhinoDoc.OpenHeadless(job["src"])
tol = doc.ModelAbsoluteTolerance
st = Rhino.DocObjects.ObjectEnumeratorSettings()
st.HiddenObjects = True
st.LockedObjects = True
st.NormalObjects = True
lay = {l.Index: l.FullPath for l in doc.Layers}
r["objects_before"] = doc.Objects.Count
fbot = [o for o in doc.Objects.GetObjectList(st) if o.Attributes.Name == "P1-FT"][0].Geometry.GetBoundingBox(True).Min.Z
breps = collections.defaultdict(list)
curves = []
for o in doc.Objects.GetObjectList(st):
g = o.Geometry
L = lay.get(o.Attributes.LayerIndex, "")
if isinstance(g, Rhino.Geometry.Brep) and "철근" in L:
breps[o.Attributes.Name].append(o)
elif isinstance(g, Rhino.Geometry.Curve) and "중심선" in L and (o.Attributes.GetUserString("mark") or "").upper().startswith("B"):
curves.append(o)
stat = collections.Counter()
plan = job["plan"]
for o in curves:
a = o.Attributes
m = a.GetUserString("mark")
if m not in plan and m not in job["rfix"]:
continue
dia = a.GetUserString("dia")
nb = breps.get(a.Name.replace("-RC-", "-R-"), [])
if len(nb) != 1:
stat[m + "_no_brep"] += 1
continue
cid, bid = o.Id, nb[0].Id
c = o.Geometry.Duplicate()
did = []
rebuild = False
dz = 0.0
if m in plan:
dz, exp, end_z = plan[m]
z0, z1 = zr(c)
if abs(z0 - fbot - exp[0]) > 0.6 or abs(z1 - fbot - exp[1]) > 0.6:
stat[m + "_unexpected_z"] += 1
continue
c.Transform(Transform.Translation(Vector3d(0, 0, dz)))
did.append("dz %+.1f" % dz)
if end_z is not None and isinstance(c, PolyCurve):
tz = fbot + end_z
n = c.SegmentCount
s0, sN = c.SegmentCurve(0), c.SegmentCurve(n - 1)
if abs(s0.TangentAtStart.Z) < 0.999 or abs(sN.TangentAtEnd.Z) < 0.999:
stat[m + "_legs_not_vertical"] += 1
continue
zs0, zsN = s0.PointAtStart.Z, sN.PointAtEnd.Z
if abs(zs0 - tz) > 1e-6 or abs(zsN - tz) > 1e-6:
segs = [c.SegmentCurve(i).DuplicateCurve() for i in range(n)]
p0, pN = segs[0].PointAtStart, segs[-1].PointAtEnd
segs[0] = _retarget(segs[0], start=Point3d(p0.X, p0.Y, tz))
segs[-1] = _retarget(segs[-1], end=Point3d(pN.X, pN.Y, tz))
pc = PolyCurve()
for s in segs:
pc.Append(s)
c = pc
did.append("legs end z %.1f" % end_z)
rebuild = True
if m in job["rfix"] and isinstance(c, PolyCurve):
pc, info = plan_curve(c, dia)
if info["status"] == "ok":
c = pc
did.append("R %.2f" % info["req"])
rebuild = True
elif info["status"] != "unchanged":
stat[m + "_rfix_" + info["status"]] += 1
if not did:
continue
if rebuild:
req, d = required_rc(dia)
pipes = make_pipe(c, d, tol)
if not pipes or len(pipes) != 1 or not pipes[0].IsSolid:
stat[m + "_pipe_fail"] += 1
continue
vol = Rhino.Geometry.VolumeMassProperties.Compute(pipes[0]).Volume
if abs(vol / (math.pi * (d / 2.0) ** 2 * c.GetLength()) - 1.0) > 0.002:
stat[m + "_volume_off"] += 1
continue
newb = pipes[0]
else:
newb = doc.Objects.FindId(bid).Geometry.Duplicate()
newb.Transform(Transform.Translation(Vector3d(0, 0, dz)))
if not (doc.Objects.Replace(cid, c) and doc.Objects.Replace(bid, newb)):
stat[m + "_replace_failed"] += 1
continue
for oid in (cid, bid):
ro = doc.Objects.FindId(oid)
at = ro.Attributes.Duplicate()
at.SetUserString("footing_fix", "; ".join(did) + " (" + DATE_TXT + ", user rule: outermost on drawing lines, inner bars inside)")
doc.Objects.ModifyAttributes(ro, at, True)
stat[m + "_done"] += 1
after = collections.defaultdict(list)
for o in doc.Objects.GetObjectList(st):
if isinstance(o.Geometry, Rhino.Geometry.Curve) and "중심선" in lay.get(o.Attributes.LayerIndex, "") and (o.Attributes.GetUserString("mark") or "").upper().startswith("B"):
after[o.Attributes.GetUserString("mark")].append(zr(o.Geometry))
r["z_after_rel"] = {mm: [round(min(z[0] for z in v) - fbot, 2), round(max(z[1] for z in v) - fbot, 2)] for mm, v in after.items()}
r["stat"] = dict(stat)
doc.Strings.SetString("수정일", DATE_TXT)
prev = doc.Strings.GetValue("수정내용") or ""
doc.Strings.SetString("수정내용", (prev + " | " if prev else "") + job["note"])
r["objects_after"] = doc.Objects.Count
r["saved"] = bool(doc.WriteFile(job["dst"], Rhino.FileIO.FileWriteOptions()))
r["out"] = job["dst"]
doc.Dispose()
return r
for key, job in JOBS.items():
try:
res[key] = run_one(key, job)
except Exception:
res[key] = {"error": traceback.format_exc()}
json.dump(res, open(OUT, "w", encoding="utf-8"), ensure_ascii=False, indent=1)
res["done"] = True
json.dump(res, open(OUT, "w", encoding="utf-8"), ensure_ascii=False, indent=1)
Loaded 100 of 3978 files, more files were not shown because too many files have changed in this diff. Show more