diff --git a/src/util/skeleton-utils.js b/src/util/skeleton-utils.js index 66734dc9..010706ea 100644 --- a/src/util/skeleton-utils.js +++ b/src/util/skeleton-utils.js @@ -431,8 +431,8 @@ export const skeletonBuilder = (roofId, canvas, textMode) => { */ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => { if (!skeleton?.Edges) return [] - const roof = canvas?.getObjects().find((object) => object.id === roofId) - const wall = canvas.getObjects().find((obj) => obj.name === POLYGON_TYPE.WALL && obj.attributes.roofId === roofId) + let roof = canvas?.getObjects().find((object) => object.id === roofId) + let wall = canvas.getObjects().find((obj) => obj.name === POLYGON_TYPE.WALL && obj.attributes.roofId === roofId) let skeletonLines = [] const processedInnerEdges = new Set() @@ -513,7 +513,7 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => { //벽라인 const wallLines = wall.lines - skeletonLines.forEach(sktLine => { + skeletonLines.forEach((sktLine, skIndex) => { let { p1, p2, attributes, lineStyle } = sktLine; // 중복방지 - 라인을 고유하게 식별할 수 있는 키 생성 (정규화된 좌표로 정렬하여 비교) @@ -532,6 +532,8 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => { { x: sktLine.p2.x, y: sktLine.p2.y } ); + //그림을 그릴때 idx 가 필요함 roof는 왼쪽부터 시작됨 - 그림그리는 순서가 필요함 + const skeletonLine = new QLine([p1.x, p1.y, p2.x, p2.y], { parentId: roof.id, fontSize: roof.fontSize, @@ -543,7 +545,7 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => { isBaseLine: sktLine.attributes.isOuterEdge, lineName: (sktLine.attributes.isOuterEdge)?'roofLine': attributes.type, selectable:(!sktLine.attributes.isOuterEdge), - roofId: roofId, + }); @@ -552,7 +554,7 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => { existingLines.add(lineKey); // 추가된 라인을 추적 - + //skeleton 라인에서 처마선은 삭제 if(skeletonLine.lineName === 'roofLine'){ const coordinateText = new fabric.Text(`(${Math.round(skeletonLine.x1)}, ${Math.round(skeletonLine.y1)})`, { @@ -596,11 +598,12 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => { //wall.lines 는 기본 벽 라인 //wall.baseLine은 움직인라인 + wall.lines.forEach((wallLine, index) => { console.log("wallLine:::::", wallLine, index) let p1,p2,p3, p4 let idx = 0; - let isMoveLine = true; + let isMoveLine = false; if (wallLine.startPoint.x !== wallLine.x1) wallLine.startPoint.x = wallLine.x1 if (wallLine.startPoint.y !== wallLine.y1) wallLine.startPoint.y = wallLine.y1 @@ -611,24 +614,72 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => { const wallLineEndPoint = {x:wallLine.x2, y:wallLine.y2} const moveLine = wall.baseLines[index] //이동한 wall 존재여부 (초기 wall line = base line) - if(isSamePoint(moveLine.startPoint, wallLineStartPoint) && isSamePoint(moveLine.endPoint, wallLineEndPoint)){ - console.log("outerLine1:::::", wallLine, idx) - isMoveLine = false; + + + + let testLine = new QLine([moveLine.x1, moveLine.y1, moveLine.x2, moveLine.y2], { + stroke: 'yellow', + strokeWidth: 10, + property: 'normal', + fontSize: 14, + }); +// Then in your code: + if (doLinesIntersect(moveLine, wallLine)) { + // Lines intersect, don't add the test line + if (testLine) { + canvas.remove(testLine); + canvas.renderAll(); + } + } else { + // Lines don't intersect, safe to add test line + if (testLine) { + canvas.remove(testLine); + } + + + canvas.add(testLine); + canvas.renderAll(); } if(isMoveLine){ + //wallLine 의 index는 맨 왼쪽 부터 0으로 변경 + + const roofIndex = (wallLine.idx === 0)? wall.lines.length : wallLine.idx //(0-6, 1-1, 2-2, 3-3 + + + + const roofLines = canvas.getObjects().filter(obj => obj.name === 'roof' && obj.id === roofId).map(obj => obj.lines).flat(); + const roofLine = roofLines[roofIndex-1]; - //현재 움직인 처마라인 const currentRoofLines = canvas .getObjects() - .filter((obj) => obj.lineName === 'roofLine' && obj.roofId === roofId) + .filter((obj) => obj.lineName === 'roofLine' && obj.parentId === roofId) + + const currentRoofLine = findClosestParallelLine(roofLine, currentRoofLines); + + const testLine2 = new QLine([roofLine.x1, roofLine.y1, roofLine.x2, roofLine.y2], { + stroke: 'red', + strokeWidth: 10, + property: 'normal', + fontSize: 14, + }) + + + const testLine3 = new QLine([currentRoofLine.x1, currentRoofLine.y1, currentRoofLine.x2, currentRoofLine.y2], { + stroke: 'blue', + strokeWidth: 10, + property: 'normal', + fontSize: 14, + }) + //canvas.add(testLine2); + canvas.add(testLine); + //canvas.add(testLine3); + canvas.renderAll() - const moveLine = wall.baseLines[index] - const roofLine = roof.lines[index] //roof 접점 @@ -638,21 +689,21 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => { const p1wallLine = findClosestRoofLine(wallLineStartPoint,wall.lines) const p2wallLine = findClosestRoofLine(wallLineEndPoint,wall.lines) //move 접점 - const p1moveLine = findClosestRoofLine(moveLine.startPoint, currentRoofLines) + const p1moveLine = findClosestRoofLine(moveLine.startPoint, wall.l) const p2moveLine = findClosestRoofLine(moveLine.endPoint, currentRoofLines) //wall move 접점 const p1outerLine = findClosestRoofLine(wallLineStartPoint, currentRoofLines) const p2outerLine = findClosestRoofLine(wallLineEndPoint, currentRoofLines) - console.log("p1RoofLineV",p1RoofLine) - console.log("p2RoofLineV",p2RoofLine) - console.log("p1wallLineV",p1wallLine) - console.log("p2wallLineV",p2wallLine) - console.log("p1moveLineV",p1moveLine) - console.log("p2moveLineV",p2moveLine) - console.log("p1outerLine",p1outerLine) - console.log("p2outerLine",p2outerLine) + // console.log("p1RoofLineV",p1RoofLine) + // console.log("p2RoofLineV",p2RoofLine) + // console.log("p1wallLineV",p1wallLine) + // console.log("p2wallLineV",p2wallLine) + // console.log("p1moveLineV",p1moveLine) + // console.log("p2moveLineV",p2moveLine) + // console.log("p1outerLine",p1outerLine) + // console.log("p2outerLine",p2outerLine) // const outerLines= canvas.getObjects().filter((obj) => obj.name === 'outerLine' && obj.attributes.roofId === roofId) // const outerLine = outerLines[index] // canvas.remove(outerLine) @@ -1080,7 +1131,7 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => { if(isPolygon){ drawPolygon( p1,p2,p3, p4) } - + // const wallLine = wall.baseLines[roofLine.idx - 1]; @@ -1098,7 +1149,7 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => { //wallLine이 baseLine의 위 또는 오른쪽에 있을때 - + // let outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine' && obj.attributes.roofId === roofId) // outerLines.forEach((outerLine) => { @@ -3286,4 +3337,131 @@ function getMovementInfo(p1, p2, newP1, newP2) { dx: dx1, dy: dy1 }; -} \ No newline at end of file +} + +function getLineAngleDirection(line, isLeftSide = true) { + const dx = line.x2 - line.x1; + const dy = line.y2 - line.y1; + + // 수평선인 경우 (y 좌표가 거의 같은 경우) + if (Math.abs(dy) < 0.1) { + // x 좌표 비교로 좌우 방향 결정 + return line.x2 > line.x1 ? 'right' : 'left'; + } + + // 수직선인 경우 (x 좌표가 거의 같은 경우) + if (Math.abs(dx) < 0.1) { + // y 좌표 비교로 상하 방향 결정 + return line.y2 > line.y1 ? 'down' : 'up'; + } + + // 대각선의 경우 기존 로직 유지 + const angle = Math.atan2(dy, dx) * (180 / Math.PI); + const normalizedAngle = (angle + 360) % 360; + + if (normalizedAngle >= 45 && normalizedAngle < 135) { + return 'up'; + } else if (normalizedAngle >= 135 && normalizedAngle < 225) { + return 'left'; + } else if (normalizedAngle >= 225 && normalizedAngle < 315) { + return 'down'; + } else { + return 'right'; + } +} + +function findRoofLineIndex(roof, p1, p2) { + if (!roof || !roof.lines || !Array.isArray(roof.lines)) { + console.error("Invalid roof object or lines array"); + return -1; + } + + // Create a tolerance for floating point comparison + const TOLERANCE = 0.1; + + // Try to find a line that matches either (p1,p2) or (p2,p1) + const index = roof.lines.findIndex(line => { + // Check if points match in order + const matchOrder = + (Math.abs(line.x1 - p1.x) < TOLERANCE && + Math.abs(line.y1 - p1.y) < TOLERANCE && + Math.abs(line.x2 - p2.x) < TOLERANCE && + Math.abs(line.y2 - p2.y) < TOLERANCE); + + // Check if points match in reverse order + const matchReverse = + (Math.abs(line.x1 - p2.x) < TOLERANCE && + Math.abs(line.y1 - p2.y) < TOLERANCE && + Math.abs(line.x2 - p1.x) < TOLERANCE && + Math.abs(line.y2 - p1.y) < TOLERANCE); + + return matchOrder || matchReverse; + }); + + if (index === -1) { + console.warn("No matching roof line found for points:", p1, p2); + } + + return index; +} + +function findClosestParallelLine(roofLine, currentRoofLines) { + // Determine if the line is horizontal or vertical + const isHorizontal = Math.abs(roofLine.y2 - roofLine.y1) < 0.001; // Using a small threshold for floating point comparison + const isVertical = Math.abs(roofLine.x2 - roofLine.x1) < 0.001; + + if (!isHorizontal && !isVertical) { + console.warn('Line is neither perfectly horizontal nor vertical'); + return null; + } + + // Calculate the reference point (midpoint of the line) + const refX = (roofLine.x1 + roofLine.x2) / 2; + const refY = (roofLine.y1 + roofLine.y2) / 2; + + let closestLine = null; + let minDistance = Infinity; + + currentRoofLines.forEach(line => { + // Skip the same line + if (line === roofLine) return; + + // Check if the line is parallel (same orientation) + const lineIsHorizontal = Math.abs(line.y2 - line.y1) < 0.001; + const lineIsVertical = Math.abs(line.x2 - line.x1) < 0.001; + + if ((isHorizontal && lineIsHorizontal) || (isVertical && lineIsVertical)) { + // Calculate midpoint of the current line + const lineMidX = (line.x1 + line.x2) / 2; + const lineMidY = (line.y1 + line.y2) / 2; + + // Calculate distance between midpoints + const distance = Math.sqrt( + Math.pow(lineMidX - refX, 2) + + Math.pow(lineMidY - refY, 2) + ); + + // Update closest line if this one is closer + if (distance < minDistance) { + minDistance = distance; + closestLine = line; + } + } + }); + + return closestLine; +} + +function doLinesIntersect(line1, line2) { + const x1 = line1.x1, y1 = line1.y1; + const x2 = line1.x2, y2 = line1.y2; + const x3 = line2.x1, y3 = line2.y1; + const x4 = line2.x2, y4 = line2.y2; + + // Calculate the direction of the lines + const uA = ((x4-x3)*(y1-y3) - (y4-y3)*(x1-x3)) / ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1)); + const uB = ((x2-x1)*(y1-y3) - (y2-y1)*(x1-x3)) / ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1)); + + // If uA and uB are between 0-1, lines are colliding + return (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1); +}