diff --git a/src/hooks/roofcover/useRoofAllocationSetting.js b/src/hooks/roofcover/useRoofAllocationSetting.js index 88e7162e..87c6ae06 100644 --- a/src/hooks/roofcover/useRoofAllocationSetting.js +++ b/src/hooks/roofcover/useRoofAllocationSetting.js @@ -670,28 +670,6 @@ export function useRoofAllocationSetting(id) { (obj.lineName === 'eaveHelpLine' || obj.lineName === 'extensionLine') && obj.roofId === roofBase.id ) - // [ALLOC-DEBUG] canvas 픽업 스냅샷 (삭제 직전 상태) - const snapByLineName = {} - const snapByName = {} - roofEaveHelpLines.forEach((o) => { - snapByLineName[o.lineName] = (snapByLineName[o.lineName] || 0) + 1 - snapByName[o.name || '?'] = (snapByName[o.name || '?'] || 0) + 1 - }) - logger.log( - `[ALLOC-DEBUG] roofBase.id=${roofBase.id} ` + - `roofBase.lines=${roofBase.lines?.length || 0} ` + - `roofBase.innerLines=${roofBase.innerLines?.length || 0} ` + - `canvas픽업=${roofEaveHelpLines.length} ` + - `byLineName=${JSON.stringify(snapByLineName)} ` + - `byName=${JSON.stringify(snapByName)}` - ) - roofEaveHelpLines.forEach((o, i) => { - logger.log( - ` [ALLOC-DEBUG] picked[${i}] name=${o.name} lineName=${o.lineName} ` + - `(${o.x1?.toFixed(1)},${o.y1?.toFixed(1)})→(${o.x2?.toFixed(1)},${o.y2?.toFixed(1)}) ` + - `len=${Math.hypot((o.x2 || 0) - (o.x1 || 0), (o.y2 || 0) - (o.y1 || 0)).toFixed(1)}` - ) - }) // logger.log('roofBase.id:', roofBase.id) // logger.log('roofEaveHelpLines:', roofEaveHelpLines) // logger.log('extensionLines found:', roofEaveHelpLines.filter(l => l.lineName === 'extensionLine')) @@ -760,20 +738,6 @@ export function useRoofAllocationSetting(id) { }); // Combine remaining lines with newEaveLines roofBase.lines = [...linesToKeep, ...normalEaveLines, ...extensionLines]; - // [ALLOC-DEBUG] 병합 결과 breakdown - logger.log( - `[ALLOC-DEBUG] 병합완료 roofBase.id=${roofBase.id} ` + - `linesToKeep=${linesToKeep.length} ` + - `normalEave=${normalEaveLines.length} ` + - `extension=${extensionLines.length} ` + - `total=${roofBase.lines.length}` - ) - roofBase.lines.forEach((ln, i) => { - logger.log( - ` [ALLOC-DEBUG] merged[${i}] name=${ln.name || '?'} lineName=${ln.lineName || '?'} ` + - `(${ln.x1?.toFixed(1)},${ln.y1?.toFixed(1)})→(${ln.x2?.toFixed(1)},${ln.y2?.toFixed(1)})` - ) - }) } else { roofBase.lines = [...roofEaveHelpLines] } @@ -813,15 +777,6 @@ export function useRoofAllocationSetting(id) { // extensionLine + 동일직선 SK 1:1 통합 (대각선 단일길이/각도 면적 산출) integrateExtensionLines(roofBase) - // [ALLOC-DEBUG] split 직전 최종 입력 - logger.log( - `[ALLOC-DEBUG] split 직전 roofBase.id=${roofBase.id} ` + - `separatePolygon=${roofBase.separatePolygon?.length || 0} ` + - `lines=${roofBase.lines?.length || 0} ` + - `innerLines=${roofBase.innerLines?.length || 0} ` + - `points=${roofBase.points?.length || 0} ` + - `→ ${roofBase.separatePolygon?.length > 0 ? 'splitPolygonWithSeparate' : 'splitPolygonWithLines'}` - ) if (roofBase.separatePolygon.length > 0) { splitPolygonWithSeparate(roofBase.separatePolygon) } else { diff --git a/src/hooks/usePolygon.js b/src/hooks/usePolygon.js index 8b2f7c37..595d63cd 100644 --- a/src/hooks/usePolygon.js +++ b/src/hooks/usePolygon.js @@ -3,7 +3,7 @@ import { useRecoilValue } from 'recoil' import { fabric } from 'fabric' import { calculateIntersection, findAndRemoveClosestPoint, getDegreeByChon, isPointOnLine } from '@/util/canvas-util' import { QPolygon } from '@/components/fabric/QPolygon' -import { isSamePoint, removeDuplicatePolygons } from '@/util/qpolygon-utils' +import { calcLinePlaneSize, isSamePoint, removeDuplicatePolygons } from '@/util/qpolygon-utils' import { basicSettingState, flowDisplaySelector } from '@/store/settingAtom' import { fontSelector } from '@/store/fontAtom' import { QLine } from '@/components/fabric/QLine' @@ -1028,7 +1028,10 @@ export const usePolygon = () => { const { intersections, startPoint, endPoint } = line // 원본 라인의 기하학적 길이 (비율 계산용) - const originalGeomLength = Math.round(Math.hypot(line.x2 - line.x1, line.y2 - line.y1)) * 10 + // [ROUND-PRECISION 2026-05-14] Math.round(hypot)*10 → calcLinePlaneSize (Big.js, ×10 후 round). + // 기존: 45.6 → Math.round(45.6)*10 = 460. 伏せ図入力 의 Big.js 경로는 456. + // 배치면 split 결과와 伏せ図入力 SK 빌더의 0.5mm boundary 가 갈리는 근본 원인. + const originalGeomLength = calcLinePlaneSize({ x1: line.x1, y1: line.y1, x2: line.x2, y2: line.y2 }) if (intersections.length === 1) { const newLinePoint1 = [line.x1, line.y1, intersections[0].x, intersections[0].y] @@ -1050,8 +1053,9 @@ export const usePolygon = () => { }) // 분할된 각 세그먼트의 기하학적 길이 - const length1 = Math.round(Math.hypot(newLine1.x1 - newLine1.x2, newLine1.y1 - newLine1.y2)) * 10 - const length2 = Math.round(Math.hypot(newLine2.x1 - newLine2.x2, newLine2.y1 - newLine2.y2)) * 10 + // [ROUND-PRECISION 2026-05-14] calcLinePlaneSize 사용 — 위 originalGeomLength 와 동일 이유. + const length1 = calcLinePlaneSize({ x1: newLine1.x1, y1: newLine1.y1, x2: newLine1.x2, y2: newLine1.y2 }) + const length2 = calcLinePlaneSize({ x1: newLine2.x1, y1: newLine2.y1, x2: newLine2.x2, y2: newLine2.y2 }) // 분할 시 새 sub-segment 의 planeSize/actualSize 는 새 기하학으로 직접 계산. // 부모 비율을 쓰면 부모 좌표 drift 가 그대로 전파되어 사용자 기대 round 값과 어긋남. @@ -1131,7 +1135,8 @@ export const usePolygon = () => { name: 'newLine', }) - const calcLength = Math.round(Math.hypot(newLine.x1 - newLine.x2, newLine.y1 - newLine.y2)) * 10 + // [ROUND-PRECISION 2026-05-14] calcLinePlaneSize 사용 — Big.js ×10 후 round. + const calcLength = calcLinePlaneSize({ x1: newLine.x1, y1: newLine.y1, x2: newLine.x2, y2: newLine.y2 }) let segPlaneSize, segActualSize if (line.attributes.planeSize && originalGeomLength > 0) { @@ -1164,7 +1169,8 @@ export const usePolygon = () => { attributes: line.attributes, name: 'newLine', }) - const lastCalcLength = Math.round(Math.hypot(newLine.x1 - newLine.x2, newLine.y1 - newLine.y2)) * 10 + // [ROUND-PRECISION 2026-05-14] calcLinePlaneSize 사용 — Big.js ×10 후 round. + const lastCalcLength = calcLinePlaneSize({ x1: newLine.x1, y1: newLine.y1, x2: newLine.x2, y2: newLine.y2 }) let lastPlaneSize, lastActualSize if (line.attributes.planeSize && originalGeomLength > 0) {