From 471093eb8a1a0ad547b0511fcf5473aa8603c90c Mon Sep 17 00:00:00 2001 From: ysCha Date: Wed, 8 Apr 2026 17:41:21 +0900 Subject: [PATCH 1/2] =?UTF-8?q?[1491]cvrLmtRow=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=A5=B8=20=EC=B2=98=EB=A7=88=EC=BB=A4=EB=B2=84=20=EB=8B=A8?= =?UTF-8?q?=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/module/useTrestle.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/hooks/module/useTrestle.js b/src/hooks/module/useTrestle.js index 411fc118..b24e28d1 100644 --- a/src/hooks/module/useTrestle.js +++ b/src/hooks/module/useTrestle.js @@ -167,9 +167,13 @@ export const useTrestle = () => { }) if (isEaveBar) { - // 처마력바설치 true인 경우 설치 - // exposedBottomModules는 아래가 노출된 최하단 모듈이므로 level 체크 없이 항상 설치 + // 처마커버 설치: cvrLmtRow 값에 따라 설치 단 수 제한 + // - cvrLmtRow=1: 최하단(level 1)만 설치 + // - cvrLmtRow=2: 최하단과 그 위 1단(level 1~2) 설치 + // - cvrLmtRow=9999: 모든 단에 설치 exposedBottomModules.forEach((module) => { + const level = module.level + if (level > cvrLmtRow) return const bottomPoints = findTopTwoPoints([...module.getCurrentPoints()], direction) if (!bottomPoints) return const eaveBar = new fabric.Line([bottomPoints[0].x, bottomPoints[0].y, bottomPoints[1].x, bottomPoints[1].y], { From 20235ac236179e5dc06415e7d5d125297b567bd1 Mon Sep 17 00:00:00 2001 From: ysCha Date: Thu, 9 Apr 2026 11:28:57 +0900 Subject: [PATCH 2/2] =?UTF-8?q?offset<->moveline=20=EB=B2=BD=EB=9D=BC?= =?UTF-8?q?=EC=9D=B8=EC=A0=95=EC=83=81=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/roofcover/useEavesGableEdit.js | 33 +++++++++++++++-- src/util/skeleton-utils.js | 45 ++++++++++++------------ 2 files changed, 53 insertions(+), 25 deletions(-) diff --git a/src/hooks/roofcover/useEavesGableEdit.js b/src/hooks/roofcover/useEavesGableEdit.js index 840ab9fc..995203f1 100644 --- a/src/hooks/roofcover/useEavesGableEdit.js +++ b/src/hooks/roofcover/useEavesGableEdit.js @@ -216,10 +216,12 @@ export function useEavesGableEdit(id) { const roofBases = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF && !obj.isFixed) - // moveLine 속성 보존 (offset 변경 후에도 마루이동 유지) + // moveLine 속성 및 이동된 baseLines 좌표 보존 const savedMoveProps = {} + const savedBaseLineCoords = {} roofBases.forEach((roof) => { if (roof.moveFlowLine || roof.moveUpDown) { + const wall = canvas.getObjects().find((obj) => obj.name === POLYGON_TYPE.WALL && obj.attributes?.roofId === roof.id) savedMoveProps[roof.id] = { moveFlowLine: roof.moveFlowLine, moveUpDown: roof.moveUpDown, @@ -227,6 +229,13 @@ export function useEavesGableEdit(id) { moveSelectLine: roof.moveSelectLine, movePosition: roof.movePosition, } + if (wall?.baseLines) { + savedBaseLineCoords[roof.id] = wall.baseLines.map((bl) => ({ + x1: bl.x1, y1: bl.y1, x2: bl.x2, y2: bl.y2, + startPoint: bl.startPoint ? { ...bl.startPoint } : undefined, + endPoint: bl.endPoint ? { ...bl.endPoint } : undefined, + })) + } } roof.innerLines.forEach((line) => { removeLine(line) @@ -245,10 +254,28 @@ export function useEavesGableEdit(id) { // moveLine 속성 복원 const saved = savedMoveProps[roof.id] if (saved) { + // 이동된 baseLines 좌표 복원 (drawRoofPolygon이 리셋한 것을 되돌림) + const savedBL = savedBaseLineCoords[roof.id] + if (savedBL && roof.wall?.baseLines) { + roof.wall.baseLines.forEach((bl, i) => { + if (!savedBL[i]) return + bl.set({ + x1: savedBL[i].x1, y1: savedBL[i].y1, + x2: savedBL[i].x2, y2: savedBL[i].y2, + startPoint: savedBL[i].startPoint, + endPoint: savedBL[i].endPoint, + }) + }) + } + // drawHelpLine 중에는 moveLine 미적용 (baseLines에 이미 반영됨) + // drawHelpLine 후 moveLine 속성 복원 + canvas?.renderAll() + roof.drawHelpLine(settingModalFirstOptions) Object.assign(roof, saved) + } else { + canvas?.renderAll() + roof.drawHelpLine(settingModalFirstOptions) } - canvas?.renderAll() - roof.drawHelpLine(settingModalFirstOptions) }) wallLines.forEach((wallLine) => { diff --git a/src/util/skeleton-utils.js b/src/util/skeleton-utils.js index 3719bd9a..22eaea64 100644 --- a/src/util/skeleton-utils.js +++ b/src/util/skeleton-utils.js @@ -404,19 +404,19 @@ export const skeletonBuilder = (roofId, canvas, textMode) => { const wall = canvas.getObjects().find((object) => object.name === POLYGON_TYPE.WALL && object.attributes.roofId === roofId) const baseLines = wall.baseLines.filter((line) => line.attributes.planeSize > 0) - // 디버그: baseLines의 offset/type/좌표 확인 - baseLines.forEach((bl, i) => { - console.log(`[skeleton] baseLine[${i}] type=${bl.attributes?.type} offset=${bl.attributes?.offset} (${Math.round(bl.x1)},${Math.round(bl.y1)})→(${Math.round(bl.x2)},${Math.round(bl.y2)})`) - }) - roof.points.forEach((p, i) => { - console.log(`[skeleton] roof.points[${i}] (${Math.round(p.x)},${Math.round(p.y)})`) - }) + // // 디버그: baseLines의 offset/type/좌표 확인 + // baseLines.forEach((bl, i) => { + // console.log(`[skeleton] baseLine[${i}] type=${bl.attributes?.type} offset=${bl.attributes?.offset} (${Math.round(bl.x1)},${Math.round(bl.y1)})→(${Math.round(bl.x2)},${Math.round(bl.y2)})`) + // }) + // roof.points.forEach((p, i) => { + // console.log(`[skeleton] roof.points[${i}] (${Math.round(p.x)},${Math.round(p.y)})`) + // }) // roof.points 순서와 맞춰야 offset 매핑이 정확함 const baseLinePoints = createOrderedBasePoints(roof.points, baseLines) - baseLinePoints.forEach((p, i) => { - console.log(`[skeleton] orderedBase[${i}] (${Math.round(p.x)},${Math.round(p.y)})`) - }) + // baseLinePoints.forEach((p, i) => { + // console.log(`[skeleton] orderedBase[${i}] (${Math.round(p.x)},${Math.round(p.y)})`) + // }) const outerLines = canvas.getObjects().filter((object) => object.name === 'outerLinePoint') || [] @@ -435,6 +435,12 @@ export const skeletonBuilder = (roofId, canvas, textMode) => { const moveFlowLine = roof.moveFlowLine || 0 const moveUpDown = roof.moveUpDown || 0 + // 디버그: offset 변경 + moveLine 상태 확인 + console.log('[DEBUG] moveFlowLine:', moveFlowLine, 'moveUpDown:', moveUpDown) + console.log('[DEBUG] wall.lines:', wall.lines.map((l, i) => `[${i}] (${Math.round(l.x1)},${Math.round(l.y1)})→(${Math.round(l.x2)},${Math.round(l.y2)})`)) + console.log('[DEBUG] wall.baseLines:', wall.baseLines.map((l, i) => `[${i}] (${Math.round(l.x1)},${Math.round(l.y1)})→(${Math.round(l.x2)},${Math.round(l.y2)})`)) + console.log('[DEBUG] roof.points:', roof.points.map((p, i) => `[${i}] (${Math.round(p.x)},${Math.round(p.y)})`)) + // 닫힌 폴리곤(첫점 = 끝점)인 경우 마지막 중복 점 제거 const isClosedPolygon = (points) => points.length > 1 && isSamePoint(points[0], points[points.length - 1]) @@ -492,10 +498,10 @@ export const skeletonBuilder = (roofId, canvas, textMode) => { // - 45도 대각 방향(signDx, signDy 각 ±1)이므로 실제 x·y 이동량은 각 축으로 maxStep const maxContactDistance = Math.hypot(maxStep, maxStep) - console.log("orderedBaseLinePoints",orderedBaseLinePoints) - console.log("contactData",contactData) - console.log("roofLineContactPoints",roofLineContactPoints) - console.log("maxContactDistance",maxContactDistance) + // console.log("orderedBaseLinePoints",orderedBaseLinePoints) + // console.log("contactData",contactData) + // console.log("roofLineContactPoints",roofLineContactPoints) + // console.log("maxContactDistance",maxContactDistance) let changRoofLinePoints = orderedBaseLinePoints.map((point, index) => { const contactPoint = roofLineContactPoints[index] @@ -512,12 +518,12 @@ export const skeletonBuilder = (roofId, canvas, textMode) => { } }) - console.log("changRoofLinePoints1:::", changRoofLinePoints) + // console.log("changRoofLinePoints1:::", changRoofLinePoints) // 6. 마루이동(용마루 위치 수동 조정)이 설정된 경우 movingLineFromSkeleton 결과로 대체 if (moveFlowLine !== 0 || moveUpDown !== 0) { const movedPoints = movingLineFromSkeleton(roofId, canvas) - console.log("movedPoints:::", movedPoints); + // console.log("movedPoints:::", movedPoints); // movedPoints를 roof 경계로 확장 // 이번 이동에서 실제로 변경된 포인트만 구분하여, 변경되지 않은 축만 roof 경계로 확장 @@ -551,12 +557,7 @@ export const skeletonBuilder = (roofId, canvas, textMode) => { changRoofLinePoints = movedPoints } - console.log("roof.points:::", roof.points) - console.log("baseLinePoints:::",baseLinePoints) - console.log("changRoofLinePoints2:::", changRoofLinePoints) - console.log("roofLineContactPoints:::", roofLineContactPoints) - console.log("roofId:::", roofId) - console.log("canvas:::", canvas) + console.log('[DEBUG] changRoofLinePoints(최종 SK입력):', changRoofLinePoints.map((p, i) => `[${i}] (${Math.round(p.x)},${Math.round(p.y)})`)) // changRoofLinePoints를 roof.skeletonPoints에 저장 (roof.points 원본은 유지) roof.skeletonPoints = changRoofLinePoints.map(p => ({ x: p.x, y: p.y }))