diff --git a/src/util/skeleton-utils.js b/src/util/skeleton-utils.js index 34d8153e..1132e9da 100644 --- a/src/util/skeleton-utils.js +++ b/src/util/skeleton-utils.js @@ -31,7 +31,8 @@ const movingRidgeFromSkeleton = (roofId, canvas) => { const startPoint = selectLine.startPoint const endPoint = selectLine.endPoint - const oldPoints = canvas?.movePoints?.points ?? roof.points + const orgPoints = roof.points; // orgPoint를 orgPoints로 변경 + const oldPoints = canvas?.skeleton.lastPoints ?? orgPoints // 여기도 변경 const oppositeLine = findOppositeLine(canvas.skeleton.Edges, startPoint, endPoint, oldPoints); if (oppositeLine) { @@ -40,50 +41,80 @@ const movingRidgeFromSkeleton = (roofId, canvas) => { console.log('No opposite line found'); } - return oldPoints.map((point) => { + + 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) + + let baseLinePoints = []; + const pointSet = new Set(); +/* + walls.forEach((wall) => { + if (wall.baseLines.length === 0) { + wall.baseLines = canvas.getObjects().filter((obj) => obj.name === 'baseLine' && obj.attributes.wallId === wall.id) + } + + // Extract points from each baseLine + wall.baseLines.forEach(line => { + console.log("useSk:::", line.x1, line.y1, line.x2, line.y2); +// 시작점과 끝점을 배열에 추가 + const points = [ + { x: line.x1, y: line.y1 }, + { x: line.x2, y: line.y2 } + ]; + + points.forEach(point => { + const key = `${point.x},${point.y}`; + if (!pointSet.has(key)) { + pointSet.add(key); + baseLinePoints.push(point); + } + }); + }); + + }) + return [...baseLinePoints]; +*/ + + return oldPoints.map((point, index) => { + + console.log('oldPoint:', point); + const originalPoint = orgPoints[index]; // orgPoint를 originalPoint로 변경 + console.log('originalPoint:', originalPoint); const newPoint = { ...point }; - const absMove = Big(moveFlowLine).abs().times(2).div(10); + const absMove = Big(moveFlowLine).times(2).div(10); //console.log('absMove:', absMove); const skeletonLines = canvas.skeletonLines; - console.log('skeleton line:', canvas.skeletonLines); - const changeSkeletonLine = (canvas, oldPoint, newPoint, str) => { - for (const line of canvas.skeletonLines) { - if (str === 'start' && isSamePoint(line.startPoint, oldPoint)) { - // Fabric.js 객체의 set 메서드로 속성 업데이트 - line.set({ - x1: newPoint.x, - y1: newPoint.y, - x2: line.x2 || line.endPoint?.x, - y2: line.y2 || line.endPoint?.y - }); - line.startPoint = newPoint; // 참조 업데이트 - } - else if (str === 'end' && isSamePoint(line.endPoint, oldPoint)) { - line.set({ - x1: line.x1 || line.startPoint?.x, - y1: line.y1 || line.startPoint?.y, - x2: newPoint.x, - y2: newPoint.y - }); - line.endPoint = newPoint; // 참조 업데이트 - } - } - canvas.requestRenderAll(); - console.log('skeleton line:', canvas.skeletonLines); - } + //console.log('skeleton line:', canvas.skeletonLines); + // const changeSkeletonLine = (canvas, oldPoint, newPoint, str) => { + // for (const line of canvas.skeletonLines) { + // if (str === 'start' && isSamePoint(line.startPoint, oldPoint)) { + // // Fabric.js 객체의 set 메서드로 속성 업데이트 + // line.set({ + // x1: newPoint.x, + // y1: newPoint.y, + // x2: line.x2 || line.endPoint?.x, + // y2: line.y2 || line.endPoint?.y + // }); + // line.startPoint = newPoint; // 참조 업데이트 + // } + // else if (str === 'end' && isSamePoint(line.endPoint, oldPoint)) { + // line.set({ + // x1: line.x1 || line.startPoint?.x, + // y1: line.y1 || line.startPoint?.y, + // x2: newPoint.x, + // y2: newPoint.y + // }); + // line.endPoint = newPoint; // 참조 업데이트 + // } + // } + // canvas.requestRenderAll(); + // console.log('skeleton line:', canvas.skeletonLines); + // } - if(moveFlowLine > 0) { - if(moveDirection === 'down'){ - moveDirection = 'up'; - }else if(moveDirection === 'left'){ - moveDirection = 'right'; - } - } - console.log('skeletonBuilder moveDirection:', moveDirection); switch (moveDirection) { @@ -92,14 +123,22 @@ const movingRidgeFromSkeleton = (roofId, canvas) => { for (const line of oppositeLine) { if (line.position === 'left') { if (isSamePoint(newPoint, line.start)) { - newPoint.x = Big(line.start.x).minus(absMove).toNumber(); - //changeSkeletonLine(canvas, line.start, newPoint, 'start') + newPoint.x = Big(line.start.x).plus(absMove).toNumber(); } else if (isSamePoint(newPoint, line.end)) { - newPoint.x = Big(line.end.x).minus(absMove).toNumber(); - //changeSkeletonLine(canvas, line.end, newPoint, 'end') + newPoint.x = Big(line.end.x).plus(absMove).toNumber(); } - break + + break; + // } else if (line.position === 'right') { + // if (isSamePoint(newPoint, line.start)) { + // newPoint.x = Big(line.start.x).minus(absMove).toNumber(); + // (newPoint.x < originalPoint.x)? newPoint.x = originalPoint.x : newPoint.x; // 변경된 이름 사용 + // }else if(isSamePoint(newPoint, line.end)) { + // newPoint.x = Big(line.end.x).minus(absMove).toNumber(); + // (newPoint.x < originalPoint.x)? newPoint.x = originalPoint.x : newPoint.x; // 변경된 이름 사용 + // } } + } break; @@ -107,29 +146,46 @@ const movingRidgeFromSkeleton = (roofId, canvas) => { for (const line of oppositeLine) { if (line.position === 'right') { if (isSamePoint(newPoint, line.start)) { - newPoint.x = Big(line.start.x).plus(absMove).toNumber(); - //changeSkeletonLine(canvas, line.start, newPoint, 'start') + newPoint.x = Big(line.start.x).minus(absMove).toNumber(); } else if (isSamePoint(newPoint, line.end)) { - newPoint.x = Big(line.end.x).plus(absMove).toNumber(); - //changeSkeletonLine(canvas, line.end, newPoint, 'end') + newPoint.x = Big(line.end.x).minus(absMove).toNumber(); } break + // }else if(line.position === 'left') { + // if (isSamePoint(newPoint, line.start)) { + // newPoint.x = Big(line.start.x).plus(absMove).toNumber(); + // (newPoint.x > originalPoint.x)? newPoint.x = originalPoint.x : newPoint.x; // 변경된 이름 사용 + // } else if (isSamePoint(newPoint, line.end)) { + // newPoint.x= Big(line.end.x).plus(absMove).toNumber(); + // (newPoint.x > originalPoint.x)? newPoint.x = originalPoint.x : newPoint.x; // 변경된 이름 사용 + // } } + } break; case 'up': // Move up: decrease Y (toward top of screen) + for (const line of oppositeLine) { if (line.position === 'top') { if (isSamePoint(newPoint, line.start)) { - newPoint.y = Big(line.start.y).minus(absMove).toNumber(); - //changeSkeletonLine(canvas, line.start, newPoint, 'start') + newPoint.y = Big(line.start.y).plus(absMove).toNumber(); } else if (isSamePoint(newPoint, line.end)) { - newPoint.y = Big(line.end.y).minus(absMove).toNumber(); - //changeSkeletonLine(canvas, line.end, newPoint, 'end') + newPoint.y = Big(line.end.y).plus(absMove).toNumber(); } - break + break; + + // }else if(line.position === 'bottom') { + // if(newPoint.y !== originalPoint.y) { + // if (isSamePoint(newPoint, line.start)) { + // newPoint.y = Big(line.start.y).minus(absMove).toNumber(); + // (newPoint.y < originalPoint.y)? newPoint.y = originalPoint.y : newPoint.y; // 변경된 이름 사용 + // }else if(isSamePoint(newPoint, line.end)) { + // newPoint.y = Big(line.end.y).minus(absMove).toNumber(); + // (newPoint.y < originalPoint.y)? newPoint.y = originalPoint.y : newPoint.y; // 변경된 이름 사용 + // } + // } } } @@ -137,23 +193,38 @@ const movingRidgeFromSkeleton = (roofId, canvas) => { case 'down': // Move down: increase Y (toward bottom of screen) for (const line of oppositeLine) { - if (line.position === 'bottom') { - if (isSamePoint(newPoint, line.start)) { - newPoint.y = Big(line.start.y).plus(absMove).toNumber(); - //changeSkeletonLine(canvas, line.start, newPoint, 'start') + if (line.position === 'bottom') { + + if (isSamePoint(newPoint, line.start)) { + newPoint.y = Big(line.start.y).minus(absMove).toNumber(); } else if (isSamePoint(newPoint, line.end)) { - newPoint.y = Big(line.end.y).plus(absMove).toNumber(); - //changeSkeletonLine(canvas, line.end, newPoint, 'end') + newPoint.y = Big(line.end.y).minus(absMove).toNumber(); } - break + + // }else if(line.position === 'top') { + // + // if(newPoint.y !== originalPoint.y) { + // + // if (isSamePoint(newPoint, line.start)) { + // newPoint.y = Big(line.start.y).plus(absMove).toNumber(); + // (newPoint.y > originalPoint.y)? newPoint.y = originalPoint.y : newPoint.y; // 변경된 이름 사용 + // } else if (isSamePoint(newPoint, line.end)) { + // newPoint.y = Big(line.end.y).plus(absMove).toNumber(); + // (newPoint.y > originalPoint.y)? newPoint.y = originalPoint.y : newPoint.y; // 변경된 이름 사용 + // } + // } + break; } + } break; } + console.log('newPoint:', newPoint); return newPoint; }) + } /** @@ -168,18 +239,13 @@ export const skeletonBuilder = (roofId, canvas, textMode) => { //처마 let roof = canvas?.getObjects().find((object) => object.id === roofId) - //벽 - const wall = canvas.getObjects().find((object) => object.name === POLYGON_TYPE.WALL && object.attributes.roofId === roofId) - // const hasNonParallelLines = roof.lines.filter((line) => Big(line.x1).minus(Big(line.x2)).gt(1) && Big(line.y1).minus(Big(line.y2)).gt(1)) - // if (hasNonParallelLines.length > 0) { - // return - // } const eavesType = [LINE_TYPE.WALLLINE.EAVES, LINE_TYPE.WALLLINE.HIPANDGABLE] const gableType = [LINE_TYPE.WALLLINE.GABLE, LINE_TYPE.WALLLINE.JERKINHEAD] /** 외벽선 */ + 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) //const skeletonLines = []; @@ -197,22 +263,20 @@ export const skeletonBuilder = (roofId, canvas, textMode) => { let points = roof.points; + + //마루이동 if (moveFlowLine !== 0) { - points = movingRidgeFromSkeleton(roofId, canvas) - const movePoints = { - points: points, - roofId: roofId, - } - canvas.set("movePoints", movePoints) + + points = movingRidgeFromSkeleton(roofId, canvas) } //처마 if(moveUpDown !== 0) { } - + console.log('points:', points); const geoJSONPolygon = toGeoJSON(points) try { @@ -232,7 +296,6 @@ export const skeletonBuilder = (roofId, canvas, textMode) => { canvas.skeletonStates[roofId] = true canvas.skeletonLines = []; canvas.skeletonLines.push(...roof.innerLines) - canvas.set("skeletonLines", canvas.skeletonLines) const cleanSkeleton = { Edges: skeleton.Edges.map(edge => ({ @@ -249,9 +312,12 @@ export const skeletonBuilder = (roofId, canvas, textMode) => { }; canvas.skeleton = []; canvas.skeleton = cleanSkeleton - + canvas.skeleton.lastPoints = points canvas.set("skeleton", cleanSkeleton); + + + canvas.renderAll() } catch (e) { console.error('스켈레톤 생성 중 오류 발생:', e) @@ -397,6 +463,23 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => { canvas.add(innerLine); innerLine.bringToFront(); existingLines.add(lineKey); // 추가된 라인을 추적 + }else{ + const coordinateText = new fabric.Text(`(${Math.round(p1.x)}, ${Math.round(p1.y)})`, { + left: p1.x + 5, // 좌표점에서 약간 오른쪽으로 이동 + top: p1.y - 20, // 좌표점에서 약간 위로 이동 + fontSize: 13, + fill: 'red', + fontFamily: 'Arial', + selectable: true, + lockMovementX: false, + lockMovementY: false, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, + name: 'lengthText' + }) + + canvas?.add(coordinateText) } innerLines.push(innerLine) canvas.renderAll(); @@ -439,7 +522,7 @@ function processEavesEdge(roofId, canvas, skeleton, edgeResult, skeletonLines) { //외벽선 밖으로 나간 선을 정리한다(roof.line의 교점까지 정리한다) // 지붕 경계선과 교차 확인 및 클리핑 const clippedLine = clipLineToRoofBoundary(p1, p2, roof.lines); - console.log('clipped line', clippedLine.p1, clippedLine.p2); + //console.log('clipped line', clippedLine.p1, clippedLine.p2); const isOuterLine = isOuterEdge(p1, p2, [edgeResult.Edge]) addRawLine(roof.id, skeletonLines, p1, p2, 'ridge', '#FF0000', 3, pitch, isOuterLine); // } @@ -627,6 +710,7 @@ const preprocessPolygonCoordinates = (initialPoints) => { if (coordinates.length > 1 && coordinates[0][0] === coordinates[coordinates.length - 1][0] && coordinates[0][1] === coordinates[coordinates.length - 1][1]) { coordinates.pop(); } + return coordinates.reverse(); }; @@ -1280,14 +1364,28 @@ function getLinePosition(line, referenceLine) { const refMidX = (referenceLine.start.x + referenceLine.end.x) / 2; const refMidY = (referenceLine.start.y + referenceLine.end.y) / 2; - // Y축 차이가 더 크면 위/아래로 판단 - // Y축 차이가 더 크면 위/아래로 판단 - if (Math.abs(lineMidY - refMidY) > Math.abs(lineMidX - refMidX)) { - return lineMidY > refMidY ? 'bottom' : 'top'; - } - // X축 차이가 더 크면 왼쪽/오른쪽으로 판단 - else { - return lineMidX > refMidX ? 'right' : 'left'; + // 참조선에 대한 벡터를 계산하여 법선 벡터 구하기 + const refVecX = referenceLine.end.x - referenceLine.start.x; + const refVecY = referenceLine.end.y - referenceLine.start.y; + + // 법선 벡터 (참조선에 수직) - 방향을 수정 + const normalX = refVecY; // -refVecY에서 refVecY로 변경 + const normalY = -refVecX; // refVecX에서 -refVecX로 변경 + + // 중점에서 중점으로의 벡터 + const midVecX = lineMidX - refMidX; + const midVecY = lineMidY - refMidY; + + // 내적을 이용해 위치 판단 + const dotProduct = midVecX * normalX + midVecY * normalY; + + // 참조선의 방향에 따라 위치 결정 + if (Math.abs(refVecX) > Math.abs(refVecY)) { + // 수평에 가까운 선분인 경우 + return dotProduct > 0 ? 'top' : 'bottom'; + } else { + // 수직에 가까운 선분인 경우 + return dotProduct > 0 ? 'right' : 'left'; } } @@ -1396,5 +1494,22 @@ function clipLineToRoofBoundary(p1, p2, roofLines) { // 교차점이 없으면 원래 선분 반환 return { p1: originalP1, p2: originalP2 }; } +export const convertBaseLinesToPoints = (baseLines) => { + const points = []; + const pointSet = new Set(); -// 기존 getLineIntersection 함수를 사용하거나, 없으면 아래 구현 사용 + baseLines.forEach((line) => { + [ + { x: line.x1, y: line.y1 }, + { x: line.x2, y: line.y2 } + ].forEach(point => { + const key = `${point.x},${point.y}`; + if (!pointSet.has(key)) { + pointSet.add(key); + points.push(point); + } + }); + }); + + return points; +}; \ No newline at end of file