diff --git a/src/hooks/roofcover/useEavesGableEdit.js b/src/hooks/roofcover/useEavesGableEdit.js index 7dc90dc5..b050fac3 100644 --- a/src/hooks/roofcover/useEavesGableEdit.js +++ b/src/hooks/roofcover/useEavesGableEdit.js @@ -3748,6 +3748,11 @@ export function useEavesGableEdit(id) { // 힙 = apex → hit (단일 직선 45°). if (apexIsE1) il.set({ x1: apex.x, y1: apex.y, x2: hit.x, y2: hit.y }) else il.set({ x1: hit.x, y1: hit.y, x2: apex.x, y2: apex.y }) + // [KERAB-TYPE-EAVES-STARTPOINT-SYNC 2026-06-12] .set 은 'modified' 를 안 띄워 startPoint/endPoint + // 가 옛 좌표로 남는다. 할당 graph(splitPolygonWithLines)는 startPoint/endPoint 로 면을 닫으므로 + // 동기화 누락 시 절삭된 힙이 옛 좌표로 연결돼 인접 roofLine 이 면에 포함되지 않아 미할당된다. + il.startPoint = { x: il.x1, y: il.y1 } + il.endPoint = { x: il.x2, y: il.y2 } const sz = calcLinePlaneSize({ x1: il.x1, y1: il.y1, x2: il.x2, y2: il.y2 }) if (il.attributes) { il.attributes.planeSize = sz @@ -3839,6 +3844,10 @@ export function useEavesGableEdit(id) { const d2 = Math.hypot(h.il.x2 - cenX, h.il.y2 - cenY) if (d1 >= d2) h.il.set({ x2: rp.x, y2: rp.y }) else h.il.set({ x1: rp.x, y1: rp.y }) + // [KERAB-TYPE-EAVES-STARTPOINT-SYNC 2026-06-12] 절삭 후 startPoint/endPoint 동기화. + // 누락 시 할당 graph 가 옛 inner 끝점으로 면을 닫으려다 실패 → 인접 roofLine 미할당. + h.il.startPoint = { x: h.il.x1, y: h.il.y1 } + h.il.endPoint = { x: h.il.x2, y: h.il.y2 } const sz = calcLinePlaneSize({ x1: h.il.x1, y1: h.il.y1, x2: h.il.x2, y2: h.il.y2 }) if (h.il.attributes) { h.il.attributes.planeSize = sz diff --git a/src/hooks/roofcover/useRoofAllocationSetting.js b/src/hooks/roofcover/useRoofAllocationSetting.js index 94688b98..b5ec24fb 100644 --- a/src/hooks/roofcover/useRoofAllocationSetting.js +++ b/src/hooks/roofcover/useRoofAllocationSetting.js @@ -1228,6 +1228,17 @@ export function useRoofAllocationSetting(id) { roofBase.innerLines.push(...made) } + // [KERAB-TYPE-EAVES-SK-HELPER-PURGE 2026-06-12] kerabPatternHip 이 있을 때 + // name='hip', lineName 미설정 인 SK 격자 반-엣지를 innerLines 에서 제거한다. + // 이 선들은 외곽 gable 변과 동일직선상에서 더 짧은 경로를 제공하여 Dijkstra 가 + // degenerate collinear face 를 먼저 선택 → 진짜 top/bottom 사다리꼴 면의 start 가 + // 소진돼 미생성된다. kerab 케이스에서만 purge — 일반 SK hip 에서는 건드리지 않음. + if (roofBase.innerLines.some((l) => l?.lineName === 'kerabPatternHip')) { + const skHelpers = roofBase.innerLines.filter((l) => !l?.lineName && l?.name === 'hip') + skHelpers.forEach((l) => canvas.remove(l)) + roofBase.innerLines = roofBase.innerLines.filter((l) => !(!l?.lineName && l?.name === 'hip')) + } + if (roofBase.separatePolygon.length > 0) { splitPolygonWithSeparate(roofBase.separatePolygon) } else {