fix: [fire-shutter] 케이스 전면판 절곡 방향 시계방향 통일

- 모든 절곡 시계방향(→↓←↑ 반복)으로 J-훅 형상 구현
- 하부: Seg2(55mm) ↓→↑ 상향, Seg1(17mm) →→← 전면복귀
- 상부: Seg7(20mm) →→← 전면복귀
- SVG 폴리곤 좌표 및 3D 플레이트 위치 전면 재계산
This commit is contained in:
김보곤
2026-03-15 10:42:51 +09:00
parent 1353ca0af5
commit 3f7eaee5ef

View File

@@ -1268,41 +1268,41 @@ function renderSbSide() {
<!-- ① 케이스 전면판 절곡 프로파일 (7세그먼트, 전개길이 ${(p.sb.frontPanel||[]).reduce((a,b)=>a+b,0)}mm) -->
${(() => {
const seg = (p.sb.frontPanel || [17,55,50,380,55,15,20]).map(v => v*sc);
// seg[0]=Seg1(17) seg[1]=Seg2(55) seg[2]=Seg3(50→) seg[3]=Seg4(380↑본체)
// seg[4]=Seg5(55→) seg[5]=Seg6(15↓) seg[6]=Seg7(20)
// 방향 패턴: 상부/하부 동일 — →내향, ↓하향, →내향
// seg[0]=Seg1(17) seg[1]=Seg2(55) seg[2]=Seg3(50→) seg[3]=Seg4(380↑본체)
// seg[4]=Seg5(55→) seg[5]=Seg6(15↓) seg[6]=Seg7(20)
// 모든 절곡 시계방향: →↓←↑ 반복 (J-훅 형상)
// 외곽면 좌표 (SVG: x→=케이스내부, y↓=하향)
const O = [
[ox+seg[4]+seg[6], oy+seg[5]], // 0: Seg7 끝 (상부 최내측)
[ox+seg[4], oy+seg[5]], // 1: Seg6 하단 / Seg7 시작
[ox+seg[4], oy], // 2: Seg5 끝 / Seg6 상단
[ox, oy], // 3: Seg4 상단 (본체 상단)
[ox, oy+sH], // 4: Seg4 하단 (본체 바닥)
[ox+seg[2], oy+sH], // 5: Seg3 끝
[ox+seg[2], oy+sH+seg[1]], // 6: Seg2 하단
[ox+seg[2]+seg[0], oy+sH+seg[1]], // 7: Seg1 끝 (하부 최내측)
[ox+seg[4]-seg[6], oy+seg[5]], // 0: Seg7 끝 (상부, ←방향 끝)
[ox+seg[4], oy+seg[5]], // 1: Seg6 하단 / Seg7 시작
[ox+seg[4], oy], // 2: Seg5 끝 / Seg6 상단
[ox, oy], // 3: Seg4 상단
[ox, oy+sH], // 4: Seg4 하단
[ox+seg[2], oy+sH], // 5: Seg3 끝
[ox+seg[2], oy+sH-seg[1]], // 6: Seg2 상단 (↑방향 끝)
[ox+seg[2]-seg[0], oy+sH-seg[1]], // 7: Seg1 끝 (하부, ←방향 끝)
];
// 내곽면 좌표 (판 두께 vt 오프셋, 오목면 방향)
// 내곽면 좌표 (시계방향 절곡 → 진행방향 우측이 내곽)
const I = [
[ox+seg[4]+seg[6], oy+seg[5]-vt], // 0: Seg7 내곽 끝
[ox+seg[4]-vt, oy+seg[5]-vt], // 1: Seg6/Seg7 내곽 코너
[ox+seg[4]-vt, oy+vt], // 2: Seg5/Seg6 내곽 코너
[ox+vt, oy+vt], // 3: Seg4/Seg5 내곽 코너 (상)
[ox+vt, oy+sH-vt], // 4: Seg4/Seg3 내곽 코너 (하)
[ox+seg[2]-vt, oy+sH-vt], // 5: Seg3/Seg2 내곽 코너
[ox+seg[2]-vt, oy+sH+seg[1]-vt], // 6: Seg2/Seg1 내곽 코너
[ox+seg[2]+seg[0], oy+sH+seg[1]-vt], // 7: Seg1 내곽 끝
[ox+seg[4]-seg[6], oy+seg[5]-vt], // 0: Seg7 내곽 끝
[ox+seg[4]-vt, oy+seg[5]-vt], // 1: Seg6/Seg7 내곽 코너
[ox+seg[4]-vt, oy+vt], // 2: Seg5/Seg6 내곽 코너
[ox+vt, oy+vt], // 3: Seg4/Seg5 내곽 코너 (상)
[ox+vt, oy+sH-vt], // 4: Seg4/Seg3 내곽 코너 (하)
[ox+seg[2]-vt, oy+sH-vt], // 5: Seg3/Seg2 내곽 코너
[ox+seg[2]-vt, oy+sH-seg[1]+vt], // 6: Seg2/Seg1 내곽 코너
[ox+seg[2]-seg[0], oy+sH-seg[1]+vt], // 7: Seg1 내곽 끝
];
const outer = [O[0],O[1],O[2],O[3],O[4],O[5],O[6],O[7]].map(p=>p.join(',')).join(' L');
const inner = [I[7],I[6],I[5],I[4],I[3],I[2],I[1],I[0]].map(p=>p.join(',')).join(' L');
const fpCol = '#60a5fa';
const lbls = [
{ x:(O[3][0]+O[2][0])/2, y:oy-6, t:'55→', r:0 }, // Seg5
{ x:O[1][0]+10, y:(O[2][1]+O[1][1])/2, t:'15↓', r:0 }, // Seg6
{ x:(O[1][0]+O[0][0])/2, y:O[0][1]+10, t:'20→', r:0 }, // Seg7
{ x:(O[4][0]+O[5][0])/2, y:O[4][1]+12, t:'50→', r:0 }, // Seg3
{ x:O[5][0]+10, y:(O[5][1]+O[6][1])/2, t:'55↓', r:0 }, // Seg2
{ x:(O[6][0]+O[7][0])/2, y:O[7][1]+10, t:'17→', r:0 }, // Seg1
{ x:(O[3][0]+O[2][0])/2, y:oy-6, t:'55→' }, // Seg5
{ x:O[1][0]+10, y:(O[2][1]+O[1][1])/2, t:'15↓' }, // Seg6
{ x:(O[1][0]+O[0][0])/2, y:O[0][1]+10, t:'20' }, // Seg7
{ x:(O[4][0]+O[5][0])/2, y:O[4][1]+12, t:'50→' }, // Seg3
{ x:O[5][0]+10, y:(O[5][1]+O[6][1])/2, t:'55↑' }, // Seg2
{ x:(O[6][0]+O[7][0])/2, y:O[7][1]-6, t:'17' }, // Seg1
];
return `
<path d="M${outer} L${inner} Z" fill="${pf}" stroke="${ps}" stroke-width="1.2" opacity="0.95"/>
@@ -1871,26 +1871,26 @@ function addPlate(w, h, d, x, y, z, mat, eMat) {
const bRearW = b.depth - bDoorW - bFrontW;
// ── ① 케이스 전면판 절곡 프로파일 (7세그먼트) ──
// 방향 패턴: 상부/하부 동일 — →내향, ↓하향, →내향
// 모든 절곡 시계방향: →↓←↑ 반복 (J-훅 형상)
const fpSeg = p.sb.frontPanel || [17, 55, 50, 380, 55, 15, 20];
// [Seg1(17), Seg2(55), Seg3(50→), Seg4(380↑본체), Seg5(55→), Seg6(15↓), Seg7(20)]
// [Seg1(17), Seg2(55), Seg3(50→), Seg4(380↑본체), Seg5(55→), Seg6(15↓), Seg7(20)]
const frontZ = b.depth / 2;
// Seg4: 본체 (전체 높이 수직면)
addPlate(W1, b.height, pt, 0, b.height / 2, frontZ - pt / 2);
// ── 상부 (본체 상단에서 내향) ──
// Seg5: 55mm → (케이스 상단에서 내향, 상판 아래)
// ── 상부 J-훅 (본체 상단 내향 → 하향 → 전면복귀) ──
// Seg5: 55mm → (케이스 상단에서 내향)
addPlate(W1, pt, fpSeg[4], 0, b.height - pt / 2, frontZ - fpSeg[4] / 2);
// Seg6: 15mm ↓ (Seg5 내측 끝에서 하향)
addPlate(W1, fpSeg[5], pt, 0, b.height - fpSeg[5] / 2, frontZ - fpSeg[4] + pt / 2);
// Seg7: 20mm (Seg6 하단에서 더 내향)
addPlate(W1, pt, fpSeg[6], 0, b.height - fpSeg[5] + pt / 2, frontZ - fpSeg[4] - fpSeg[6] / 2);
// ── 하부 (본체 하단에서 내향) ──
// Seg7: 20mm (Seg6 하단에서 전면 방향으로 복귀)
addPlate(W1, pt, fpSeg[6], 0, b.height - fpSeg[5] + pt / 2, frontZ - fpSeg[4] + fpSeg[6] / 2);
// ── 하부 J-훅 (본체 하단 내향 → 상향 → 전면복귀) ──
// Seg3: 50mm → (케이스 바닥에서 내향)
addPlate(W1, pt, fpSeg[2], 0, pt / 2, frontZ - fpSeg[2] / 2);
// Seg2: 55mm (Seg3 끝에서 케이스 아래로)
addPlate(W1, fpSeg[1], pt, 0, -fpSeg[1] / 2, frontZ - fpSeg[2] + pt / 2);
// Seg1: 17mm (Seg2 단에서 더 내향)
addPlate(W1, pt, fpSeg[0], 0, -fpSeg[1] + pt / 2, frontZ - fpSeg[2] - fpSeg[0] / 2);
// Seg2: 55mm (Seg3 끝에서 케이스 내부 위로)
addPlate(W1, fpSeg[1], pt, 0, fpSeg[1] / 2, frontZ - fpSeg[2] + pt / 2);
// Seg1: 17mm (Seg2 단에서 전면 방향으로 복귀)
addPlate(W1, pt, fpSeg[0], 0, fpSeg[1] - pt / 2, frontZ - fpSeg[2] + fpSeg[0] / 2);
// ── ② 상판 (전체 깊이 고정) ──
addPlate(W1, pt, b.depth, 0, b.height - pt / 2, 0);