From 175a177f4d5a447efa7d48ac0a3ebd30730d3a49 Mon Sep 17 00:00:00 2001 From: ysCha Date: Tue, 30 Dec 2025 10:52:22 +0900 Subject: [PATCH] =?UTF-8?q?=EB=9D=BC=EC=9D=B8=EB=A8=B8=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/skeleton-utils.js | 136 +++++++++++++++++++------------------ 1 file changed, 69 insertions(+), 67 deletions(-) diff --git a/src/util/skeleton-utils.js b/src/util/skeleton-utils.js index 5db8af4d..8d0d3469 100644 --- a/src/util/skeleton-utils.js +++ b/src/util/skeleton-utils.js @@ -692,51 +692,51 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => { const sortRoofLines = ensureCounterClockwiseLines(roofLines) // roofLines의 방향에 맞춰 currentRoofLines의 방향을 조정 - const alignLineDirection = (sourceLines, targetLines) => { - return sourceLines.map((sourceLine) => { - // 가장 가까운 targetLine 찾기 - const nearestTarget = targetLines.reduce((nearest, targetLine) => { - const sourceCenter = { - x: (sourceLine.x1 + sourceLine.x2) / 2, - y: (sourceLine.y1 + sourceLine.y2) / 2, - } - const targetCenter = { - x: (targetLine.x1 + targetLine.x2) / 2, - y: (targetLine.y1 + targetLine.y2) / 2, - } - const distance = Math.hypot(sourceCenter.x - targetCenter.x, sourceCenter.y - targetCenter.y) - - return !nearest || distance < nearest.distance ? { line: targetLine, distance } : nearest - }, null)?.line - - if (!nearestTarget) return sourceLine - - // 방향이 반대인지 확인 (벡터 내적을 사용) - const sourceVec = { - x: sourceLine.x2 - sourceLine.x1, - y: sourceLine.y2 - sourceLine.y1, - } - const targetVec = { - x: nearestTarget.x2 - nearestTarget.x1, - y: nearestTarget.y2 - nearestTarget.y1, - } - - const dotProduct = sourceVec.x * targetVec.x + sourceVec.y * targetVec.y - - // 내적이 음수이면 방향이 반대이므로 뒤집기 - if (dotProduct < 0) { - return { - ...sourceLine, - x1: sourceLine.x2, - y1: sourceLine.y2, - x2: sourceLine.x1, - y2: sourceLine.y1, - } - } - - return sourceLine - }) - } + // const alignLineDirection = (sourceLines, targetLines) => { + // return sourceLines.map((sourceLine) => { + // // 가장 가까운 targetLine 찾기 + // const nearestTarget = targetLines.reduce((nearest, targetLine) => { + // const sourceCenter = { + // x: (sourceLine.x1 + sourceLine.x2) / 2, + // y: (sourceLine.y1 + sourceLine.y2) / 2, + // } + // const targetCenter = { + // x: (targetLine.x1 + targetLine.x2) / 2, + // y: (targetLine.y1 + targetLine.y2) / 2, + // } + // const distance = Math.hypot(sourceCenter.x - targetCenter.x, sourceCenter.y - targetCenter.y) + // + // return !nearest || distance < nearest.distance ? { line: targetLine, distance } : nearest + // }, null)?.line + // + // if (!nearestTarget) return sourceLine + // + // // 방향이 반대인지 확인 (벡터 내적을 사용) + // const sourceVec = { + // x: sourceLine.x2 - sourceLine.x1, + // y: sourceLine.y2 - sourceLine.y1, + // } + // const targetVec = { + // x: nearestTarget.x2 - nearestTarget.x1, + // y: nearestTarget.y2 - nearestTarget.y1, + // } + // + // const dotProduct = sourceVec.x * targetVec.x + sourceVec.y * targetVec.y + // + // // 내적이 음수이면 방향이 반대이므로 뒤집기 + // if (dotProduct < 0) { + // return { + // ...sourceLine, + // x1: sourceLine.x2, + // y1: sourceLine.y2, + // x2: sourceLine.x1, + // y2: sourceLine.y1, + // } + // } + // + // return sourceLine + // }) + // } console.log('wallBaseLines', wall.baseLines) @@ -762,9 +762,31 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => { console.log('wallBaseLine:', wallBaseLine.x1, wallBaseLine.y1, wallBaseLine.x2, wallBaseLine.y2) console.log('isSamePoint result:', isSameLine2(wallBaseLine, wallLine)) + const isCollinear = (l1, l2, tolerance = 0.1) => { + const slope1 = Math.abs(l1.x2 - l1.x1) < tolerance ? Infinity : (l1.y2 - l1.y1) / (l1.x2 - l1.x1) + const slope2 = Math.abs(l2.x2 - l2.x1) < tolerance ? Infinity : (l2.y2 - l2.y1) / (l2.x2 - l2.x1) + + if (slope1 === Infinity && slope2 === Infinity) { + return Math.abs(l1.x1 - l2.x1) < tolerance + } + + if (Math.abs(slope1 - slope2) > tolerance) return false + + const yIntercept1 = l1.y1 - slope1 * l1.x1 + const yIntercept2 = l2.y1 - slope2 * l2.x1 + + return Math.abs(yIntercept1 - yIntercept2) < tolerance + } + + if (isCollinear(wallBaseLine, wallLine)) { + return + } + if (isSameLine2(wallBaseLine, wallLine)) { return } + + const movedStart = Math.abs(wallBaseLine.x1 - wallLine.x1) > EPSILON || Math.abs(wallBaseLine.y1 - wallLine.y1) > EPSILON const movedEnd = Math.abs(wallBaseLine.x2 - wallLine.x2) > EPSILON || Math.abs(wallBaseLine.y2 - wallLine.y2) > EPSILON @@ -3572,6 +3594,7 @@ function isValleyVertex(targetPoint, connectedLine, allLines, isStartVertex) { } const crossProduct = getTurnDirection(p1, p2, p3); + console.log('crossProduct:', crossProduct); return crossProduct > 0; } @@ -3595,32 +3618,11 @@ function findInteriorPoint(line, polygonLines) { // 2. 끝점이 골짜기인지 확인 const endIsValley = isValleyVertex(currentLine.endPoint, currentLine, polygonLines, false); - // 3. 라인의 방향성 확인 - const isHorizontal = y1 === y2; // 정확히 수평 - const isVertical = x1 === x2; // 정확히 수직 - const isLeftToRight = x1 < x2; // 왼쪽에서 오른쪽 방향 - const isTopToBottom = y1 < y2; // 위에서 아래 방향 - // 4. 평행한 라인 중에서 start 또는 end가 true인 경우 isParallelWithValley = true - let isParallelWithValley = false; - if (isHorizontal || isVertical) { - if (isHorizontal) { - // 수평선인 경우: 왼쪽이 start, 오른쪽이 end - if ((isLeftToRight && startIsValley) || (!isLeftToRight && endIsValley)) { - isParallelWithValley = true; - } - } else { - // 수직선인 경우: 위가 start, 아래가 end - if ((isTopToBottom && startIsValley) || (!isTopToBottom && endIsValley)) { - isParallelWithValley = true; - } - } - } return { start: startIsValley, - end: endIsValley, - isParallel: isParallelWithValley + end: endIsValley }; }