From e10e0d5b582dda1f4b19d0c074c171fab4af2c49 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Tue, 30 Jul 2024 17:55:30 +0900 Subject: [PATCH] =?UTF-8?q?sortedPoints=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/canvas-util.js | 128 +++++++--------------------------------- 1 file changed, 21 insertions(+), 107 deletions(-) diff --git a/src/util/canvas-util.js b/src/util/canvas-util.js index e7bdb373..d7a740ef 100644 --- a/src/util/canvas-util.js +++ b/src/util/canvas-util.js @@ -292,56 +292,6 @@ export const getDirectionByPoint = (a, b) => { } } -/** - * 두 선분의 교차점을 찾는 함수입니다. 이 함수는 두 선분이 실제로 교차하는 지점 내에서 교차하는지 확인합니다. - * @param {Object} line1 첫 번째 선분, {x1, y1, x2, y2} 형태의 객체 - * @param {Object} line2 두 번째 선분, {x1, y1, x2, y2} 형태의 객체 - * @returns {{x: number, y: number}|null} 교차점의 좌표를 반환하거나, 교차점이 없으면 null을 반환합니다. - */ -export function calculateIntersection(line1, line2) { - const { x1: x1_1, y1: y1_1, x2: x2_1, y2: y2_1 } = line1 - const { x1: x1_2, y1: y1_2, x2: x2_2, y2: y2_2 } = line2 - - const denominator = (x1_1 - x2_1) * (y1_2 - y2_2) - (y1_1 - y2_1) * (x1_2 - x2_2) - if (denominator === 0) return null // 선분이 평행하거나 일치하는 경우 - - const t = ((x1_1 - x1_2) * (y1_2 - y2_2) - (y1_1 - y1_2) * (x1_2 - x2_2)) / denominator - const u = -((x1_1 - x2_1) * (y1_1 - y1_2) - (y1_1 - y2_1) * (x1_1 - x1_2)) / denominator - - // t와 u가 모두 0과 1 사이에 있을 때, 선분 내에서 교차 - if (t >= 0 && t <= 1 && u >= 0 && u <= 1) { - const intersectionX = x1_1 + t * (x2_1 - x1_1) - const intersectionY = y1_1 + t * (y2_1 - y1_1) - - // Determine the min and max for line1 and line2 for both x and y - const line1MinX = Math.min(line1.x1, line1.x2) - const line1MaxX = Math.max(line1.x1, line1.x2) - const line2MinX = Math.min(line2.x1, line2.x2) - const line2MaxX = Math.max(line2.x1, line2.x2) - - const line1MinY = Math.min(line1.y1, line1.y2) - const line1MaxY = Math.max(line1.y1, line1.y2) - const line2MinY = Math.min(line2.y1, line2.y2) - const line2MaxY = Math.max(line2.y1, line2.y2) - - // 교차점이 선분의 범위 내에 있는지 확인 - if ( - intersectionX >= line1MinX && - intersectionX <= line1MaxX && - intersectionX >= line2MinX && - intersectionX <= line2MaxX && - intersectionY >= line1MinY && - intersectionY <= line1MaxY && - intersectionY >= line2MinY && - intersectionY <= line2MaxY - ) { - return { x: Math.round(intersectionX), y: Math.round(intersectionY) } - } - } - - return null // 교차점이 선분의 범위 내에 없음 -} - export const findIntersection1 = (line1, line2) => { const { x1, y1, x2, y2 } = line1 // 첫 번째 선의 두 점 @@ -372,7 +322,7 @@ export const findIntersection1 = (line1, line2) => { return { x, y } } -export const calculateIntersection2 = (line1, line2) => { +export const calculateIntersection = (line1, line2) => { const result = intersect([line1.x1, line1.y1], [line1.x2, line1.y2], [line2.x1, line2.y1], [line2.x2, line2.y2]) if (!result) { @@ -425,68 +375,32 @@ export function findOrthogonalPoint(line1, line2) { */ export const sortedPoints = (points) => { const copyPoints = [...points] - //points를 x,y좌표를 기준으로 정렬합니다. - copyPoints.sort((a, b) => { - if (a.x === b.x) { - return a.y - b.y - } - return a.x - b.x + copyPoints.forEach((point) => { + point.x1 = point.x + point.y1 = point.y + const nextPoint = copyPoints[(copyPoints.indexOf(point) + 1) % copyPoints.length] + point.x2 = nextPoint.x + point.y2 = nextPoint.y }) - // 이때 copyPoints를 순회하며 최초엔 x값을 비교하여 같은 점을 찾는다. 이때 이 점이 2번째 점이 된다. - // 그 다음점은 2번째 점과 y값이 같은 점이 된다. - // 또 그다음 점은 3번째 점과 x값이 같은 점이 된다. - // 이를 반복하여 copyPoints를 재배열한다. - const resultPoints = [copyPoints[0]] - let index = 1 - let currentPoint = { ...copyPoints[0] } - copyPoints.splice(0, 1) - while (index < points.length) { - if (index === points.length - 1) { - resultPoints.push(copyPoints[0]) - index++ - break - } else if (index % 2 === 0) { - // 짝수번째는 y값이 같은 점을 찾는다. - for (let i = 0; i < copyPoints.length; i++) { - // y값이 같은 point가 많은 경우 그 중 x값이 가장 큰걸 찾는다. - let temp = copyPoints.filter((point) => point.y === currentPoint.y) - if (temp.length === 0) { - // temp가 비어있을 경우 copyPoints에서 가장 가까운 점을 찾는다. - temp = Array.of(findClosestPointByY(currentPoint, copyPoints)) - } - // temp중 x값이 가장 가까운 값 + // copyPoint에서 x1, y1 값을 기준으로 정렬 후 첫번째 값 + const startIndex = getStartIndex(copyPoints) - const min = temp.reduce((prev, current) => (Math.abs(current.x - currentPoint.x) <= Math.abs(prev.x - currentPoint.x) ? current : prev)) + const resultPoints = [copyPoints[startIndex]] - resultPoints.push(min) - currentPoint = min - copyPoints.splice(copyPoints.indexOf(min), 1) - index++ - break - } - } else { - // 홀수번째는 x값이 같은 점을 찾는다. - for (let i = 0; i < copyPoints.length; i++) { - // x값이 같은 point가 많은 경우 그 중 y값이 가장 큰걸 찾는다. - let temp = copyPoints.filter((point) => point.x === currentPoint.x) - if (temp.length === 0) { - // temp가 비어있을 경우 copyPoints에서 가장 가까운 점을 찾는다. + let currentPoint = copyPoints[startIndex] - temp = Array.of(findClosestPointByX(currentPoint, copyPoints)) - } - // temp중 y값이 가장 가까운 값 - const min = temp.reduce((prev, current) => (Math.abs(current.y - currentPoint.y) <= Math.abs(prev.y - currentPoint.y) ? current : prev)) + copyPoints.forEach((point, index) => { + if (index === startIndex) return - resultPoints.push(min) - currentPoint = min - copyPoints.splice(copyPoints.indexOf(min), 1) - index++ - break - } - } - } - return resultPoints + const nextPoint = copyPoints.find((p) => p.x1 === currentPoint.x2 && p.y1 === currentPoint.y2) + resultPoints.push(nextPoint) + currentPoint = nextPoint + }) + + return resultPoints.map((point) => { + return { x: point.x, y: point.y } + }) } /**