라인머지

This commit is contained in:
ysCha 2025-12-30 10:52:22 +09:00
parent ee3998c795
commit 175a177f4d

View File

@ -692,51 +692,51 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
const sortRoofLines = ensureCounterClockwiseLines(roofLines) const sortRoofLines = ensureCounterClockwiseLines(roofLines)
// roofLines의 방향에 맞춰 currentRoofLines의 방향을 조정 // roofLines의 방향에 맞춰 currentRoofLines의 방향을 조정
const alignLineDirection = (sourceLines, targetLines) => { // const alignLineDirection = (sourceLines, targetLines) => {
return sourceLines.map((sourceLine) => { // return sourceLines.map((sourceLine) => {
// 가장 가까운 targetLine 찾기 // // 가장 가까운 targetLine 찾기
const nearestTarget = targetLines.reduce((nearest, targetLine) => { // const nearestTarget = targetLines.reduce((nearest, targetLine) => {
const sourceCenter = { // const sourceCenter = {
x: (sourceLine.x1 + sourceLine.x2) / 2, // x: (sourceLine.x1 + sourceLine.x2) / 2,
y: (sourceLine.y1 + sourceLine.y2) / 2, // y: (sourceLine.y1 + sourceLine.y2) / 2,
} // }
const targetCenter = { // const targetCenter = {
x: (targetLine.x1 + targetLine.x2) / 2, // x: (targetLine.x1 + targetLine.x2) / 2,
y: (targetLine.y1 + targetLine.y2) / 2, // y: (targetLine.y1 + targetLine.y2) / 2,
} // }
const distance = Math.hypot(sourceCenter.x - targetCenter.x, sourceCenter.y - targetCenter.y) // const distance = Math.hypot(sourceCenter.x - targetCenter.x, sourceCenter.y - targetCenter.y)
//
return !nearest || distance < nearest.distance ? { line: targetLine, distance } : nearest // return !nearest || distance < nearest.distance ? { line: targetLine, distance } : nearest
}, null)?.line // }, null)?.line
//
if (!nearestTarget) return sourceLine // if (!nearestTarget) return sourceLine
//
// 방향이 반대인지 확인 (벡터 내적을 사용) // // 방향이 반대인지 확인 (벡터 내적을 사용)
const sourceVec = { // const sourceVec = {
x: sourceLine.x2 - sourceLine.x1, // x: sourceLine.x2 - sourceLine.x1,
y: sourceLine.y2 - sourceLine.y1, // y: sourceLine.y2 - sourceLine.y1,
} // }
const targetVec = { // const targetVec = {
x: nearestTarget.x2 - nearestTarget.x1, // x: nearestTarget.x2 - nearestTarget.x1,
y: nearestTarget.y2 - nearestTarget.y1, // y: nearestTarget.y2 - nearestTarget.y1,
} // }
//
const dotProduct = sourceVec.x * targetVec.x + sourceVec.y * targetVec.y // const dotProduct = sourceVec.x * targetVec.x + sourceVec.y * targetVec.y
//
// 내적이 음수이면 방향이 반대이므로 뒤집기 // // 내적이 음수이면 방향이 반대이므로 뒤집기
if (dotProduct < 0) { // if (dotProduct < 0) {
return { // return {
...sourceLine, // ...sourceLine,
x1: sourceLine.x2, // x1: sourceLine.x2,
y1: sourceLine.y2, // y1: sourceLine.y2,
x2: sourceLine.x1, // x2: sourceLine.x1,
y2: sourceLine.y1, // y2: sourceLine.y1,
} // }
} // }
//
return sourceLine // return sourceLine
}) // })
} // }
console.log('wallBaseLines', wall.baseLines) 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('wallBaseLine:', wallBaseLine.x1, wallBaseLine.y1, wallBaseLine.x2, wallBaseLine.y2)
console.log('isSamePoint result:', isSameLine2(wallBaseLine, wallLine)) 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)) { if (isSameLine2(wallBaseLine, wallLine)) {
return return
} }
const movedStart = Math.abs(wallBaseLine.x1 - wallLine.x1) > EPSILON || Math.abs(wallBaseLine.y1 - wallLine.y1) > EPSILON 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 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); const crossProduct = getTurnDirection(p1, p2, p3);
console.log('crossProduct:', crossProduct);
return crossProduct > 0; return crossProduct > 0;
} }
@ -3595,32 +3618,11 @@ function findInteriorPoint(line, polygonLines) {
// 2. 끝점이 골짜기인지 확인 // 2. 끝점이 골짜기인지 확인
const endIsValley = isValleyVertex(currentLine.endPoint, currentLine, polygonLines, false); 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 { return {
start: startIsValley, start: startIsValley,
end: endIsValley, end: endIsValley
isParallel: isParallelWithValley
}; };
} }