diff --git a/src/hooks/useContextMenu.js b/src/hooks/useContextMenu.js index 97adc452..cedc4cdf 100644 --- a/src/hooks/useContextMenu.js +++ b/src/hooks/useContextMenu.js @@ -43,6 +43,8 @@ import { useTrestle } from './module/useTrestle' import { useCircuitTrestle } from './useCirCuitTrestle' import { usePolygon } from '@/hooks/usePolygon' import { useText } from '@/hooks/useText' +import { POLYGON_TYPE } from '@/common/common' +import { debugCapture } from '@/util/debugCapture' export function useContextMenu() { const canvas = useRecoilValue(canvasState) @@ -382,16 +384,47 @@ export function useContextMenu() { name: getMessage('contextmenu.auxiliary.remove'), fn: () => { if (!currentObject) return - const roof = canvas.getObjects().filter((obj) => obj.id === currentObject.attributes.roofId)[0] + const co = currentObject + // [처마선 삭제 면분할 반영 2026-06-15] 기존 '보조선 삭제'는 roof.innerLines/canvas 에서만 지우고 + // roof.lines(외곽 처마선)는 건드리지 않았다. 그래서 외곽 처마선(eaveHelpLine)을 이 메뉴로 지워도 + // 면분할 입력(splitPolygonWithLines 의 polygon.lines)엔 그대로 남아, 그 변이 닫는 면(예: 위 사다리꼴)이 + // 계속 생성됐다(GETSPLIT-IO 진단). 삭제 대상과 같은 좌표의 변을 roof.lines 에서도 제거해 삭제를 면분할까지 반영한다. + const pEq = (ax, ay, bx, by) => Math.abs(ax - bx) <= 2 && Math.abs(ay - by) <= 2 + const sameSeg = (l) => + l.id === co.id || + (pEq(l.x1, l.y1, co.x1, co.y1) && pEq(l.x2, l.y2, co.x2, co.y2)) || + (pEq(l.x1, l.y1, co.x2, co.y2) && pEq(l.x2, l.y2, co.x1, co.y1)) + // roofId 로 roof 찾기 — eaveHelpLine 은 attributes.roofId 가 없을 수 있어 roofId 도 본다. + const roofId = co.attributes?.roofId ?? co.roofId + let roof = canvas.getObjects().find((obj) => obj.name === POLYGON_TYPE.ROOF && obj.id === roofId) + // id 로 못 찾으면 같은 좌표의 변을 가진 roof 를 탐색 if (!roof) { - // 아직 innerLines로 세팅이 안되어있는 line인 경우 제거 - canvas.remove(currentObject) - canvas.discardActiveObject() - return + roof = canvas.getObjects().find((obj) => obj.name === POLYGON_TYPE.ROOF && Array.isArray(obj.lines) && obj.lines.some(sameSeg)) } - const innerLines = roof.innerLines?.filter((line) => currentObject.id !== line.id) - roof.innerLines = [...innerLines] - canvas.remove(currentObject) + const beforeLines = roof?.lines?.length ?? 0 + const beforeInner = roof?.innerLines?.length ?? 0 + if (roof) { + if (Array.isArray(roof.innerLines)) roof.innerLines = roof.innerLines.filter((l) => !sameSeg(l)) + if (Array.isArray(roof.lines)) roof.lines = roof.lines.filter((l) => !sameSeg(l)) + } + debugCapture.log('AUX-REMOVE-DIAG', { + co: { + name: co.name, + lineName: co.lineName, + id: co.id?.slice?.(0, 8), + roofId: co.roofId?.slice?.(0, 8), + attrRoofId: co.attributes?.roofId?.slice?.(0, 8), + x1: Math.round(co.x1 * 10) / 10, + y1: Math.round(co.y1 * 10) / 10, + x2: Math.round(co.x2 * 10) / 10, + y2: Math.round(co.y2 * 10) / 10, + }, + roofFound: !!roof, + roofId: roof?.id?.slice?.(0, 8), + lines: `${beforeLines}→${roof?.lines?.length ?? 0}`, + innerLines: `${beforeInner}→${roof?.innerLines?.length ?? 0}`, + }) + canvas.remove(co) canvas.discardActiveObject() }, },