From d54103943d8605d212f712b9fde7dacf51c3111b Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 9 May 2025 13:45:10 +0900 Subject: [PATCH 01/11] =?UTF-8?q?0=EB=B2=88=EC=A7=B8=EC=9D=BC=20=EA=B2=BD?= =?UTF-8?q?=EC=9A=B0=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/qpolygon-utils.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 475d2ae6..1af80680 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -314,15 +314,22 @@ export function removeDuplicatePolygons(polygons) { // 현재 point의 x와 이전 포인트의 x와 같을경우, 다음 포인트의 x와 달라야 함. // 현재 point의 y와 이전 포인트의 y와 같을경우, 다음 포인트의 y와 달라야 함. const isValidPoints = (points) => { - for (let i = 1; i < points.length; i++) { - let prev = points[i - 1] - let curr = points[i] - let next = points[i + 1] - - if (i === points.length - 1) { + let prev + let curr + let next + for (let i = 0; i < points.length; i++) { + if (i === 0) { + prev = points[points.length - 1] + curr = points[i] + next = points[i + 1] + } else if (i === points.length - 1) { prev = points[i - 1] curr = points[i] next = points[0] + } else { + prev = points[i - 1] + curr = points[i] + next = points[i + 1] } // 현재와 이전의 x가 같다면 다음의 x는 달라야 함 From 553cbd44dbc86a5b157402fbf513a1dea59d0398 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 9 May 2025 16:52:04 +0900 Subject: [PATCH 02/11] =?UTF-8?q?=EC=98=A4=EC=B0=A8=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/canvas-util.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/util/canvas-util.js b/src/util/canvas-util.js index 0f0b69dc..5955cbce 100644 --- a/src/util/canvas-util.js +++ b/src/util/canvas-util.js @@ -360,16 +360,16 @@ export const calculateIntersection = (line1, line2) => { // Check if the intersection X and Y are within the range of both lines if ( - result[0] >= line1MinX && - result[0] <= line1MaxX && - result[0] >= line2MinX && - result[0] <= line2MaxX && - result[1] >= line1MinY && - result[1] <= line1MaxY && - result[1] >= line2MinY && - result[1] <= line2MaxY + result[0] >= line1MinX - 1 && + result[0] <= line1MaxX + 1 && + result[0] >= line2MinX - 1 && + result[0] <= line2MaxX + 1 && + result[1] >= line1MinY - 1 && + result[1] <= line1MaxY + 1 && + result[1] >= line2MinY - 1 && + result[1] <= line2MaxY + 1 ) { - return { x: Math.round(result[0]), y: Math.round(result[1]) } + return { x: result[0], y: result[1] } } else { return null // Intersection is out of range } From f48a8b31d370981e5dceabb3628b5a8678e9b9e4 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Mon, 12 May 2025 14:09:48 +0900 Subject: [PATCH 03/11] =?UTF-8?q?=EC=A7=80=EB=B6=95=EC=9E=AC=20=EB=B6=84?= =?UTF-8?q?=ED=95=A0=20=EC=8B=9C=20addLengthText=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/usePolygon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hooks/usePolygon.js b/src/hooks/usePolygon.js index 4d59d292..735a85f5 100644 --- a/src/hooks/usePolygon.js +++ b/src/hooks/usePolygon.js @@ -1160,7 +1160,7 @@ export const usePolygon = () => { }) canvas.add(roof) - addLengthText(roof) + // addLengthText(roof) canvas.remove(polygon) canvas.renderAll() }) From f4ba3058c7443b67406d12461bf84315983cacc6 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Mon, 12 May 2025 16:04:53 +0900 Subject: [PATCH 04/11] =?UTF-8?q?range=20=EA=B3=84=EC=82=B0=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/canvas-util.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util/canvas-util.js b/src/util/canvas-util.js index 5955cbce..9420e910 100644 --- a/src/util/canvas-util.js +++ b/src/util/canvas-util.js @@ -536,8 +536,8 @@ export function isPointOnLine({ x1, y1, x2, y2 }, { x, y }, epsilon = 2) { if (Math.abs(crossProduct) > 1000) return false // 작은 오차 허용 // 점이 선분의 범위 내에 있는지 확인 - const withinXRange = Math.abs(Math.min(x1, x2) - x) <= 2 || 2 <= Math.abs(Math.max(x1, x2) - x) - const withinYRange = Math.abs(Math.min(y1, y2) - y) <= 2 || 2 <= Math.abs(Math.max(y1, y2) - y) + const withinXRange = Math.min(x1, x2) - x <= 2 && 2 <= Math.max(x1, x2) - x + const withinYRange = Math.min(y1, y2) - y <= 2 && 2 <= Math.max(y1, y2) - y return withinXRange && withinYRange } From 976396cd787a0b30f66668494e2fdda9fecfe288 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Mon, 12 May 2025 18:18:31 +0900 Subject: [PATCH 05/11] =?UTF-8?q?valid=EC=97=90=20=ED=95=B4=EB=8B=B9?= =?UTF-8?q?=ED=95=98=EC=A7=80=EC=95=8A=EB=8A=94=20polygon=EC=9D=B4=202?= =?UTF-8?q?=EA=B0=9C=20=EC=9D=B4=EC=83=81=EC=9D=BC=20=EA=B2=BD=EC=9A=B0=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/qpolygon-utils.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 1af80680..280245c6 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -304,9 +304,19 @@ export function removeDuplicatePolygons(polygons) { } }) - uniquePolygons = uniquePolygons.filter((polygon) => { - return isValidPoints(polygon) - }) + //uniquePolygons중 isValidPoints의 조건을 만족하는 카운트 계산 + const validCount = uniquePolygons.reduce((acc, polygon) => { + if (!isValidPoints(polygon)) { + return acc + 1 + } + return acc + }, 0) + + if (validCount > 1) { + uniquePolygons = uniquePolygons.filter((polygon) => { + return isValidPoints(polygon) + }) + } return uniquePolygons } From 72c020aceaf9eedbc9d2852e4acf4177d13c2dd0 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Tue, 13 May 2025 09:57:36 +0900 Subject: [PATCH 06/11] =?UTF-8?q?pointOnLine=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 | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/util/canvas-util.js b/src/util/canvas-util.js index 9420e910..3e3f4059 100644 --- a/src/util/canvas-util.js +++ b/src/util/canvas-util.js @@ -535,9 +535,21 @@ export function isPointOnLine({ x1, y1, x2, y2 }, { x, y }, epsilon = 2) { const crossProduct = (y - y1) * (x2 - x1) - (x - x1) * (y2 - y1) if (Math.abs(crossProduct) > 1000) return false // 작은 오차 허용 + const isSameX = Math.abs(x1 - x2) < 2 + const isSameY = Math.abs(y1 - y2) < 2 + // 점이 선분의 범위 내에 있는지 확인 - const withinXRange = Math.min(x1, x2) - x <= 2 && 2 <= Math.max(x1, x2) - x - const withinYRange = Math.min(y1, y2) - y <= 2 && 2 <= Math.max(y1, y2) - y + let withinXRange = Math.min(x1, x2) - x <= 2 + if (!isSameX) { + withinXRange = withinXRange && 2 <= Math.max(x1, x2) - x + } + + let withinYRange = Math.min(y1, y2) - y <= 2 + if (!isSameY) { + withinYRange = withinYRange && 2 <= Math.max(y1, y2) - y + } + + console.log(Math.min(x1, x2) - x, Math.max(x1, x2) - x) return withinXRange && withinYRange } From c52d914c6e940edf8e80eb7d895d01a690c301fc Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Tue, 13 May 2025 10:55:58 +0900 Subject: [PATCH 07/11] =?UTF-8?q?validCheck=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/qpolygon-utils.js | 67 +++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 280245c6..d13a9e54 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -304,19 +304,9 @@ export function removeDuplicatePolygons(polygons) { } }) - //uniquePolygons중 isValidPoints의 조건을 만족하는 카운트 계산 - const validCount = uniquePolygons.reduce((acc, polygon) => { - if (!isValidPoints(polygon)) { - return acc + 1 - } - return acc - }, 0) - - if (validCount > 1) { - uniquePolygons = uniquePolygons.filter((polygon) => { - return isValidPoints(polygon) - }) - } + uniquePolygons = uniquePolygons.filter((polygon) => { + return isValidPoints(polygon) + }) return uniquePolygons } @@ -324,34 +314,43 @@ export function removeDuplicatePolygons(polygons) { // 현재 point의 x와 이전 포인트의 x와 같을경우, 다음 포인트의 x와 달라야 함. // 현재 point의 y와 이전 포인트의 y와 같을경우, 다음 포인트의 y와 달라야 함. const isValidPoints = (points) => { - let prev - let curr - let next - for (let i = 0; i < points.length; i++) { - if (i === 0) { - prev = points[points.length - 1] - curr = points[i] - next = points[i + 1] - } else if (i === points.length - 1) { - prev = points[i - 1] - curr = points[i] - next = points[0] - } else { - prev = points[i - 1] - curr = points[i] - next = points[i + 1] - } + function isColinear(p1, p2, p3) { + return (p2.x - p1.x) * (p3.y - p1.y) === (p3.x - p1.x) * (p2.y - p1.y) + } - // 현재와 이전의 x가 같다면 다음의 x는 달라야 함 - if (Math.abs(curr.x - prev.x) < 1 && Math.abs(curr.x - next.x) < 1) { + function segmentsOverlap(a1, a2, b1, b2) { + // 같은 직선 상에 있는가? + if (!isColinear(a1, a2, b1) || !isColinear(a1, a2, b2)) { return false } - // 현재와 이전의 y가 같다면 다음의 y는 달라야 함 - if (Math.abs(curr.y - prev.y) < 1 && Math.abs(curr.y - next.y) < 1) { + const isHorizontal = a1.y === a2.y + if (isHorizontal) { + const aMin = Math.min(a1.x, a2.x), + aMax = Math.max(a1.x, a2.x) + const bMin = Math.min(b1.x, b2.x), + bMax = Math.max(b1.x, b2.x) + return Math.max(aMin, bMin) < Math.min(aMax, bMax) + } else { + const aMin = Math.min(a1.y, a2.y), + aMax = Math.max(a1.y, a2.y) + const bMin = Math.min(b1.y, b2.y), + bMax = Math.max(b1.y, b2.y) + return Math.max(aMin, bMin) < Math.min(aMax, bMax) + } + } + + for (let i = 0; i < points.length - 2; i++) { + const a1 = points[i] + const a2 = points[i + 1] + const b1 = points[i + 1] // 연속되는 점 + const b2 = points[i + 2] + + if (segmentsOverlap(a1, a2, b1, b2)) { return false } } + return true } From 7bf548de2b8ec3eb6374340c02270dfad2af39fb Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Tue, 13 May 2025 14:22:25 +0900 Subject: [PATCH 08/11] =?UTF-8?q?=EC=A3=BC=EC=84=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/qpolygon-utils.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index d13a9e54..a3f78cb6 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -311,8 +311,7 @@ export function removeDuplicatePolygons(polygons) { return uniquePolygons } -// 현재 point의 x와 이전 포인트의 x와 같을경우, 다음 포인트의 x와 달라야 함. -// 현재 point의 y와 이전 포인트의 y와 같을경우, 다음 포인트의 y와 달라야 함. +// 같은 직선상에 있는지 확인 같은 직선이라면 polygon을 생성할 수 없으므로 false const isValidPoints = (points) => { function isColinear(p1, p2, p3) { return (p2.x - p1.x) * (p3.y - p1.y) === (p3.x - p1.x) * (p2.y - p1.y) From bac3fbef70da593efd8c4756b33859ce31b50845 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Tue, 13 May 2025 14:34:10 +0900 Subject: [PATCH 09/11] =?UTF-8?q?addLengthText=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 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hooks/usePolygon.js b/src/hooks/usePolygon.js index 735a85f5..3fd5fd2e 100644 --- a/src/hooks/usePolygon.js +++ b/src/hooks/usePolygon.js @@ -1160,7 +1160,8 @@ export const usePolygon = () => { }) canvas.add(roof) - // addLengthText(roof) + canvas.renderAll() + addLengthText(roof) canvas.remove(polygon) canvas.renderAll() }) From d06733ed4cfb31449217f75e2485eaa7fec00685 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Tue, 13 May 2025 14:36:11 +0900 Subject: [PATCH 10/11] =?UTF-8?q?=EC=9B=90=EB=B3=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/usePolygon.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/hooks/usePolygon.js b/src/hooks/usePolygon.js index 3fd5fd2e..735a85f5 100644 --- a/src/hooks/usePolygon.js +++ b/src/hooks/usePolygon.js @@ -1160,8 +1160,7 @@ export const usePolygon = () => { }) canvas.add(roof) - canvas.renderAll() - addLengthText(roof) + // addLengthText(roof) canvas.remove(polygon) canvas.renderAll() }) From 001c1cfd95a118e197ad4ba8c1c943e38f7ab9dd Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Tue, 13 May 2025 14:46:57 +0900 Subject: [PATCH 11/11] =?UTF-8?q?useEffect=EB=82=B4=EB=B6=80=20async=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/floor-plan/CanvasFrame.jsx | 45 ++++++++++++----------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/src/components/floor-plan/CanvasFrame.jsx b/src/components/floor-plan/CanvasFrame.jsx index b43fd559..4e0a14c0 100644 --- a/src/components/floor-plan/CanvasFrame.jsx +++ b/src/components/floor-plan/CanvasFrame.jsx @@ -36,28 +36,31 @@ import { useMasterController } from '@/hooks/common/useMasterController' export default function CanvasFrame() { const [roofMaterials, setRoofMaterials] = useRecoilState(roofMaterialsAtom) const { getRoofMaterialList } = useMasterController() - useEffect(async () => { - if (roofMaterials.length !== 0) { - return - } - const { data } = await getRoofMaterialList() + useEffect(() => { + async function initRoofMaterial() { + if (roofMaterials.length !== 0) { + return + } + const { data } = await getRoofMaterialList() - const roofLists = data.map((item, idx) => ({ - ...item, - id: item.roofMatlCd, - name: item.roofMatlNm, - selected: idx === 0, - index: idx, - nameJp: item.roofMatlNmJp, - length: item.lenBase && parseInt(item.lenBase), - width: item.widBase && parseInt(item.widBase), - raft: item.raftBase && parseInt(item.raftBase), - layout: ['ROOF_ID_SLATE', 'ROOF_ID_SINGLE'].includes(item.roofMatlCd) ? ROOF_MATERIAL_LAYOUT.STAIRS : ROOF_MATERIAL_LAYOUT.PARALLEL, - hajebichi: item.roofPchBase && parseInt(item.roofPchBase), - pitch: item.pitch ? parseInt(item.pitch) : 4, - angle: item.angle ? parseInt(item.angle) : 21.8, - })) - setRoofMaterials(roofLists) + const roofLists = data.map((item, idx) => ({ + ...item, + id: item.roofMatlCd, + name: item.roofMatlNm, + selected: idx === 0, + index: idx, + nameJp: item.roofMatlNmJp, + length: item.lenBase && parseInt(item.lenBase), + width: item.widBase && parseInt(item.widBase), + raft: item.raftBase && parseInt(item.raftBase), + layout: ['ROOF_ID_SLATE', 'ROOF_ID_SINGLE'].includes(item.roofMatlCd) ? ROOF_MATERIAL_LAYOUT.STAIRS : ROOF_MATERIAL_LAYOUT.PARALLEL, + hajebichi: item.roofPchBase && parseInt(item.roofPchBase), + pitch: item.pitch ? parseInt(item.pitch) : 4, + angle: item.angle ? parseInt(item.angle) : 21.8, + })) + setRoofMaterials(roofLists) + } + initRoofMaterial() }, []) const canvasRef = useRef(null) const { canvas } = useCanvas('canvas')