From a45bba3a7bc0e2dfad959d7c5d363be81dc310ab Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Tue, 29 Apr 2025 14:26:21 +0900 Subject: [PATCH] =?UTF-8?q?=EC=98=A4=EC=B0=A8=EB=B2=94=EC=9C=84=20?= =?UTF-8?q?=EA=B3=84=EC=82=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/usePolygon.js | 82 +++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 32 deletions(-) diff --git a/src/hooks/usePolygon.js b/src/hooks/usePolygon.js index 9a5f39f8..43a78eae 100644 --- a/src/hooks/usePolygon.js +++ b/src/hooks/usePolygon.js @@ -822,10 +822,10 @@ export const usePolygon = () => { line.endPoint = endPoint }) - polygonLines.forEach((line) => { + /*polygonLines.forEach((line) => { line.set({ strokeWidth: 10 }) canvas.add(line) - }) + })*/ canvas.renderAll() polygonLines.forEach((line) => { @@ -1148,31 +1148,47 @@ export const usePolygon = () => { } const getSplitRoofsPoints = (startLines, allLines, innerLines, uniquePoints) => { + // ==== Utility functions ==== + + function isSamePoint(p1, p2, epsilon = 1) { + return Math.abs(p1.x - p2.x) <= epsilon && Math.abs(p1.y - p2.y) <= epsilon + } + + function normalizePoint(p, epsilon = 1) { + return { + x: Math.round(p.x / epsilon) * epsilon, + y: Math.round(p.y / epsilon) * epsilon, + } + } + + function pointToKey(p, epsilon = 1) { + const norm = normalizePoint(p, epsilon) + return `${norm.x},${norm.y}` + } + // 거리 계산 function calcDistance(p1, p2) { return Math.hypot(p2.x - p1.x, p2.y - p1.y) } - // 바로 연결 체크 - function isDirectlyConnected(start, end, graph) { - const startKey = `${start.x},${start.y}` - if (!graph[startKey]) return false - return graph[startKey].some((neighbor) => neighbor.point.x === end.x && neighbor.point.y === end.y) - } + // ==== Direct edge check ==== - // Dijkstra 최단 경로 - function findShortestPath(start, end, graph) { - const startKey = `${start.x},${start.y}` - const endKey = `${end.x},${end.y}` + function isDirectlyConnected(start, end, graph, epsilon = 1) { + const startKey = pointToKey(start, epsilon) + return (graph[startKey] || []).some((neighbor) => isSamePoint(neighbor.point, end, epsilon)) + } + // ==== Dijkstra pathfinding ==== + + function findShortestPath(start, end, graph, epsilon = 1) { + const startKey = pointToKey(start, epsilon) + const endKey = pointToKey(end, epsilon) const distances = {} const previous = {} const visited = new Set() const queue = [{ key: startKey, dist: 0 }] - for (const key in graph) { - distances[key] = Infinity - } + for (const key in graph) distances[key] = Infinity distances[startKey] = 0 while (queue.length > 0) { @@ -1181,8 +1197,8 @@ export const usePolygon = () => { if (visited.has(key)) continue visited.add(key) - for (const neighbor of graph[key]) { - const neighborKey = `${neighbor.point.x},${neighbor.point.y}` + for (const neighbor of graph[key] || []) { + const neighborKey = pointToKey(neighbor.point, epsilon) const alt = distances[key] + neighbor.distance if (alt < distances[neighborKey]) { distances[neighborKey] = alt @@ -1192,35 +1208,37 @@ export const usePolygon = () => { } } - // 경로 복구 const path = [] let currentKey = endKey - if (!previous[currentKey]) { - return null // 경로 없음 - } + if (!previous[currentKey]) return null while (currentKey !== startKey) { const [x, y] = currentKey.split(',').map(Number) path.unshift({ x, y }) currentKey = previous[currentKey] } - path.unshift(start) + + const [sx, sy] = startKey.split(',').map(Number) + path.unshift({ x: sx, y: sy }) return path } // 최종 함수 - function getPath(start, end, graph) { - if (isDirectlyConnected(start, end, graph)) { + function getPath(start, end, graph, epsilon = 1) { + if (isDirectlyConnected(start, end, graph, epsilon)) { + console.log('직선 연결 있음. 무시.') return null - } else { - const path = findShortestPath(start, end, graph) - if (!path || path.length < 3) { - return null - } - return path } + + const path = findShortestPath(start, end, graph, epsilon) + if (!path || path.length < 3) { + console.log('경로 존재하나 3개 미만 좌표. 무시.') + return null + } + + return path } const roofs = [] @@ -1235,8 +1253,8 @@ export const usePolygon = () => { }) for (const [p1, p2] of edges) { - const key1 = `${p1.x},${p1.y}` - const key2 = `${p2.x},${p2.y}` + const key1 = pointToKey(p1) + const key2 = pointToKey(p2) const distance = calcDistance(p1, p2) if (!graph[key1]) graph[key1] = []