From db7ea8c67616031b5d162b70e544e3ad9d64d7fd Mon Sep 17 00:00:00 2001 From: ysCha Date: Wed, 24 Jun 2026 14:45:50 +0900 Subject: [PATCH] =?UTF-8?q?[=EA=B3=A8=EC=A7=9C=EA=B8=B0=EB=A7=88=EB=A3=A8]?= =?UTF-8?q?=20A=ED=83=80=EC=9E=85=20=EC=83=9D=EC=84=B1=20=EC=8B=9C=20?= =?UTF-8?q?=EA=B3=A8=EC=A7=9C=EA=B8=B0=20=EB=B0=95=EC=8A=A4=EB=9D=BC?= =?UTF-8?q?=EC=9D=B8(B)=20=EC=B6=94=EA=B0=80=20=E2=80=94=20=EB=A7=88?= =?UTF-8?q?=EB=A3=A8=EC=99=80=20=EB=B3=84=EA=B0=9C=EB=A1=9C=20=E5=87=BA?= =?UTF-8?q?=E5=B9=85=20=EA=B2=B9=EC=B9=A8=20=EA=B2=BD=EA=B3=84=20=EC=9C=A0?= =?UTF-8?q?=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [작업내용] : - drawGableRoof 후처리: 평행 두 마루가 수직축으로 겹치면(골짜기) 짧은 마루 위치에 겹침구간 박스라인(kerabValleyOverlapLine, 라벨 B) 생성 - drawValleyBoxLine 헬퍼 추가 — 마루 삭제해도 박스 경계 잔존(박스라인+마루) - 진단 로그([GABLE-H8-*][VALLEY-BOX-FILL]) 주석화 + logger import 제거 Co-Authored-By: Claude Opus 4 --- src/util/qpolygon-utils.js | 69 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 97e1d394..3aac6cdf 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1569,6 +1569,7 @@ export const drawGableRoof = (roofId, canvas, textMode) => { //각 포인트들을 직교하도록 정렬 const sortedPoints = getSortedOrthogonalPoints(roofPlanePoint) + // logger.log(`[GABLE-H8-PLANE] planeDir ridges=${ridgeLines.length}`) sortedPoints.forEach((currPoint, index) => { const nextPoint = sortedPoints[(index + 1) % sortedPoints.length] const points = [currPoint.x, currPoint.y, nextPoint.x, nextPoint.y] @@ -1617,6 +1618,7 @@ export const drawGableRoof = (roofId, canvas, textMode) => { if (Math.abs(rg.y1 - points[1]) >= 1) return false return Math.min(rg.x1, rg.x2) - 1 <= sMin && sMax <= Math.max(rg.x1, rg.x2) + 1 }) + // logger.log(`[GABLE-H8-CHK] seg covered=${coveredByRidge ? 'YES' : 'NO'}`) if (coveredByRidge) { return true } @@ -1651,6 +1653,52 @@ export const drawGableRoof = (roofId, canvas, textMode) => { drawRoofPlane(backward) }) roof.innerLines.push(...ridgeLines, ...innerLines) + + // [VALLEY-BOX-FILL 2026-06-24] 골짜기에서 평행한 두 마루가 수직축으로 겹치면(出幅 겹침=박스), + // 짧은 마루 쪽 위치에 겹침구간을 잇는 세로 박스라인(라벨 B)을 채운다. + // 마루는 건드리지 않고(박스라인+마루) 박스 경계만 보강 → 마루 삭제해도 경계 유지. + { + const VB_EPS = 1 + for (let i = 0; i < ridgeLines.length; i++) { + for (let j = i + 1; j < ridgeLines.length; j++) { + const a = ridgeLines[i] + const b = ridgeLines[j] + const aV = Math.abs(a.x1 - a.x2) < VB_EPS + const bV = Math.abs(b.x1 - b.x2) < VB_EPS + const aH = Math.abs(a.y1 - a.y2) < VB_EPS + const bH = Math.abs(b.y1 - b.y2) < VB_EPS + let pts = null + if (aV && bV && Math.abs(a.x1 - b.x1) > VB_EPS) { + const aMin = Math.min(a.y1, a.y2) + const aMax = Math.max(a.y1, a.y2) + const bMin = Math.min(b.y1, b.y2) + const bMax = Math.max(b.y1, b.y2) + const o0 = Math.max(aMin, bMin) + const o1 = Math.min(aMax, bMax) + if (o1 - o0 > VB_EPS) { + const fillX = aMax - aMin <= bMax - bMin ? a.x1 : b.x1 + pts = [fillX, o0, fillX, o1] + } + } else if (aH && bH && Math.abs(a.y1 - b.y1) > VB_EPS) { + const aMin = Math.min(a.x1, a.x2) + const aMax = Math.max(a.x1, a.x2) + const bMin = Math.min(b.x1, b.x2) + const bMax = Math.max(b.x1, b.x2) + const o0 = Math.max(aMin, bMin) + const o1 = Math.min(aMax, bMax) + if (o1 - o0 > VB_EPS) { + const fillY = aMax - aMin <= bMax - bMin ? a.y1 : b.y1 + pts = [o0, fillY, o1, fillY] + } + } + if (pts) { + // logger.log(`[VALLEY-BOX-FILL] box`) + roof.innerLines.push(drawValleyBoxLine(pts, canvas, roof, roof.textMode)) + } + } + } + } + // 처마선 innerLine 이 외곽선/치수를 전담하므로 roof 원본 외곽(stroke) 숨김 + 지붕선 치수(roof lengthText) 제거. // 외벽선(wall) 치수는 유지. (박공은 split 공용 함수를 안 거치므로 여기서 직접 처리) roof.set({ stroke: 'transparent' }) @@ -5934,6 +5982,27 @@ const drawRidgeLine = (points, canvas, roof, textMode) => { return ridge } +// [VALLEY-BOX-FILL 2026-06-24] 골짜기 박스(出幅 겹침)의 세로변을 마루와 별개의 박스라인으로 채운다. +// kerabValleyOverlapLine(라벨 B) 으로 만들어 마루를 지워도 박스 경계가 남도록 한다(박스라인+마루). +const drawValleyBoxLine = (points, canvas, roof, textMode) => { + const lsz = calcLinePlaneSize({ x1: points[0], y1: points[1], x2: points[2], y2: points[3] }) + const box = new QLine(points, { + parentId: roof.id, + fontSize: roof.fontSize, + stroke: '#1083E3', + strokeWidth: 3, + name: LINE_TYPE.SUBLINE.VALLEY, + textMode: textMode, + attributes: { roofId: roof.id, type: 'kerabValleyOverlapLine', isStart: true, pitch: roof.pitch, planeSize: lsz, actualSize: lsz }, + }) + box.lineName = 'kerabValleyOverlapLine' + box.roofId = roof.id + canvas.add(box) + box.bringToFront() + canvas.renderAll() + return box +} + /** * 지붕선을 그린다. * @param points