fix: [fire-shutter] 스크린 가이드레일 flange 30mm 수정 (슬롯 10mm)

- flange:8→30 (양쪽 30mm씩 → 슬롯 개구부 10mm)
- lip=10mm는 슬랫이 통과하는 홈 폭 (width-2*flange=10mm)
- 평면도 클립을 채널 내부 사이드월 면으로 재배치
- 3D 클립을 사이드월 내면 L형 브라켓으로 수정
- 슬롯 갭 치수 표시 추가
This commit is contained in:
김보곤
2026-03-09 18:06:02 +09:00
parent e5886f77e5
commit d58cf44a64

View File

@@ -401,7 +401,7 @@
openHeight: 3000,
quantity: 1,
// Guide Rail
gr: { width:70, depth:120, thickness:1.55, lip:10, flange:8, sideWall:80, backWall:67, trimThick:1.2, sealThick:0.8, sealDepth:40, slatThick:0.8, anchorSpacing:500, viewMode:'cross', showDim:true, showSeal:true },
gr: { width:70, depth:120, thickness:1.55, lip:10, flange:30, sideWall:80, backWall:67, trimThick:1.2, sealThick:0.8, sealDepth:40, slatThick:0.8, anchorSpacing:500, viewMode:'cross', showDim:true, showSeal:true },
// Shutter Box
sb: { width:2280, height:380, depth:500, thickness:1.6, shaftDia:80, bracketW:10, motorSide:'right', viewMode:'front', showShaft:true, showSlatRoll:true, showMotor:true, showBrake:true, showSpring:true },
// 3D
@@ -420,7 +420,7 @@
sb:{height:550, depth:650, frontH:410, bottomOpen:75, shaftDia:120},
bk:{nmH:320, nmD:320, mtH:320, mtD:530, thick:18, sprocketR:215, motorSpR:40, motorOffset:160} },
screen: { marginW:140, marginH:350, weightFactor:2,
gr:{width:70, depth:120, thickness:1.55, lip:10, flange:8, sideWall:80, backWall:67, trimThick:1.2},
gr:{width:70, depth:120, thickness:1.55, lip:10, flange:30, sideWall:80, backWall:67, trimThick:1.2},
slatThick:0.8,
sb:{height:380, depth:500, frontH:240, bottomOpen:75, shaftDia:80},
bk:{nmH:180, nmD:180, mtH:180, mtD:380, thick:18, sprocketR:70, motorSpR:30, motorOffset:0} },
@@ -734,7 +734,7 @@ function renderGrCross() {
const sw = (g.sideWall || 80) * sc; // 80mm 사이드월
const t = g.thickness * sc; // 1.55mm
const bodyD = sw + t; // ~82mm 본체 깊이 (가로)
const fl = (g.flange || 8) * sc; // 8mm 플랜지
const fl = (g.flange || 30) * sc; // 30mm 플랜지 (슬롯=width-2*fl=10mm)
const lp = g.lip * sc; // 10mm 립
const sealT = g.sealThick * sc;
const sealD = g.sealDepth * sc;
@@ -807,13 +807,17 @@ function renderGrCross() {
const slatX1 = bx + t + 2;
const slatX2 = bx + bodyD - lp - t - 2;
// ① 클립 (개구부쪽, 플랜지 내면에서 안쪽으로)
const clipLen = Math.min(15 * sc, (fw - 2*fl) * 0.15);
const clipW = Math.max(t, 3);
// ① 클립 (채널 내부, 사이드월 내면에 부착 — 참조 도면 기준)
// 클립은 개구부 근처 채널 넓은 공간에 L형 브라켓으로 위치
const clipSize = 15 * sc; // 15mm 클립 크기
const clipT = Math.max(t, 3); // 클립 두께
const clipX = bx + bodyD - lp - t - clipSize - 4; // 개구부 근처 (립 안쪽)
const clipY1 = by + t + 4; // 상단 사이드월 내면
const clipY2 = by + fw - t - clipSize - 4; // 하단 사이드월 내면
const clipSvg = `
<rect x="${bx+bodyD-lp-t-clipLen}" y="${by+fl+t}" width="${clipLen}" height="${clipW}" fill="#8b5cf6" opacity="0.5" rx="1"/>
<rect x="${bx+bodyD-lp-t-clipLen}" y="${by+fw-fl-t-clipW}" width="${clipLen}" height="${clipW}" fill="#8b5cf6" opacity="0.5" rx="1"/>
${g.showDim ? `<text x="${bx+bodyD-lp-t-clipLen-2}" y="${by+fl+t+clipW+10}" fill="#8b5cf6" font-size="7" font-weight="700" text-anchor="end" font-family="Pretendard"></text>` : ''}`;
<rect x="${clipX}" y="${clipY1}" width="${clipSize}" height="${clipSize}" fill="none" stroke="#8b5cf6" stroke-width="${clipT}" opacity="0.5" rx="1"/>
<rect x="${clipX}" y="${clipY2}" width="${clipSize}" height="${clipSize}" fill="none" stroke="#8b5cf6" stroke-width="${clipT}" opacity="0.5" rx="1"/>
${g.showDim ? `<text x="${clipX+clipSize+4}" y="${clipY1+clipSize/2+3}" fill="#8b5cf6" font-size="7" font-weight="700" text-anchor="start" font-family="Pretendard"></text>` : ''}`;
// 치수선
let dimLines = '';
@@ -833,9 +837,13 @@ function renderGrCross() {
// 플랜지 (우측 상단)
dimLines += `<line x1="${bx+bodyD+3}" y1="${by}" x2="${bx+bodyD+3}" y2="${by+fl}" stroke="#94a3b8" stroke-width="0.8"/>`;
dimLines += `<text x="${bx+bodyD+8}" y="${by+fl/2+3}" fill="#94a3b8" font-size="9" font-weight="700" text-anchor="start" font-family="Pretendard">FL ${g.flange}</text>`;
// 립 길이 (우측 플랜지 아래)
// 슬롯 개구부 (우측 플랜지 사이)
const slotGap = g.width - 2 * g.flange;
dimLines += `<line x1="${bx+bodyD}" y1="${by+fl+3}" x2="${bx+bodyD}" y2="${by+fw-fl-3}" stroke="#22c55e" stroke-width="0.8"/>`;
dimLines += `<text x="${bx+bodyD+6}" y="${by+fw/2+3}" fill="#22c55e" font-size="8" font-weight="700" text-anchor="start" font-family="Pretendard">슬롯 ${slotGap}</text>`;
// 립 깊이 (개구부→채널 방향)
dimLines += `<line x1="${bx+bodyD-lp}" y1="${by+fl+3}" x2="${bx+bodyD}" y2="${by+fl+3}" stroke="#94a3b8" stroke-width="0.8"/>`;
dimLines += `<text x="${bx+bodyD-lp/2}" y="${by+fl+14}" fill="#94a3b8" font-size="9" font-weight="700" text-anchor="middle" font-family="Pretendard">립 ${g.lip}</text>`;
dimLines += `<text x="${bx+bodyD-lp/2}" y="${by+fl+14}" fill="#94a3b8" font-size="9" font-weight="700" text-anchor="middle" font-family="Pretendard">립깊이 ${g.lip}</text>`;
// 두께
dimLines += `<text x="${bx+t}" y="${by+fw+55}" fill="#94a3b8" font-size="9" font-weight="700" font-family="Pretendard">t=${g.thickness}</text>`;
}
@@ -1645,13 +1653,13 @@ function createRailGroup() {
if (isScreen) {
// ====== 스크린형 가이드레일 (실제 조립 구조) ======
// 단면 좌표계: X=폭(0→70), Y=깊이(0=개구부/실내측, +=벽쪽)
const fl = g.flange; // 8mm (플랜지)
const fl = g.flange; // 30mm (플랜지, 슬롯=width-2*fl=10mm)
const lp = g.lip; // 10mm (립)
const sw = g.sideWall; // 80mm (사이드월)
const bw = g.backWall; // 67mm (백월)
// --- ② 본체 (EGI 1.55T): 10-26-80-67-80-26-10 ---
// C채널: 사이드월 80mm, 백월 67mm, 플랜지 26mm, 립 10mm
// --- ② 본체 (EGI 1.55T): 슬롯10-플랜지30-사이드월80-백월t-사이드월80-플랜지30-슬롯 ---
// C채널: 사이드월 80mm, 플랜지 30mm, 슬롯 개구부 10mm (=width-2*fl)
const bodyShape = new THREE.Shape();
// 외곽 (시계방향)
bodyShape.moveTo(0, 0); // 하단-전면 모서리
@@ -1747,22 +1755,22 @@ function createRailGroup() {
tt.lineTo(rw + trimT, -9);
grp.add(new THREE.Mesh(new THREE.ExtrudeGeometry(tt, railExtrude), railSusMat));
// --- ① 마감재 (EGI 1.55T): 10-11-110-30-15-15-15 × 2개 ---
// 슬랫 가이드 클립: 채널 내부에서 슬랫을 잡아주는 ㄱ자 클립
const clipSeg = [10, 11, 110, 30, 15, 15, 15];
// 상단/하단 각 1개씩 — 플랜지 내면에 부착
[fl + rt, rw - fl - rt].forEach((clipX, idx) => {
const clipDir = idx === 0 ? 1 : -1; // 채널 중심 방향
// --- ① 마감재 (EGI 1.55T) × 2개 ---
// 슬랫 가이드 클립: 사이드월 내면에 부착된 L형 브라켓
// 참조 도면 기준: 채널 내부 사이드월에서 안쪽으로 돌출
[{ x: rt, dir: 1 }, { x: rw - rt, dir: -1 }].forEach(({ x, dir }) => {
const clipShape = new THREE.Shape();
// 간략화: 주요 가이드 돌출부만 표현 (30mm×15mm ㄱ자)
const cy = lp + rt + 5; // 립 내면에서 약간 안쪽
clipShape.moveTo(clipX, cy);
clipShape.lineTo(clipX + clipDir * 15, cy);
clipShape.lineTo(clipX + clipDir * 15, cy + 30);
clipShape.lineTo(clipX + clipDir * 15 - clipDir * rt, cy + 30);
clipShape.lineTo(clipX + clipDir * 15 - clipDir * rt, cy + rt);
clipShape.lineTo(clipX, cy + rt);
clipShape.lineTo(clipX, cy);
const cy = lp + rt + 3; // 립 내면에서 약간 안쪽
const armLen = 12; // 사이드월에서 안쪽으로 돌출 길이
const legLen = 20; // 사이드월 따라 길이
// L형 브라켓 (사이드월 내면 → 채널 안쪽으로)
clipShape.moveTo(x, cy);
clipShape.lineTo(x + dir * armLen, cy);
clipShape.lineTo(x + dir * armLen, cy + rt);
clipShape.lineTo(x + dir * rt, cy + rt);
clipShape.lineTo(x + dir * rt, cy + legLen);
clipShape.lineTo(x, cy + legLen);
clipShape.lineTo(x, cy);
const clipGeo = new THREE.ExtrudeGeometry(clipShape, railExtrude);
grp.add(new THREE.Mesh(clipGeo, railMat));
});