From 22b99534011209ce02d45eb59216e121ed0def59 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 9 Aug 2024 16:19:04 +0900 Subject: [PATCH 1/4] =?UTF-8?q?=EB=AA=A8=EC=9E=84=EC=A7=80=EB=B6=95=20?= =?UTF-8?q?=EB=8B=A8=EA=B3=84=20=EB=B6=84=ED=95=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Roof2.jsx | 9 ++++-- src/hooks/useCanvas.js | 6 ++-- src/hooks/useMode.js | 64 +++++++++++++++++++++++++++++----------- 3 files changed, 58 insertions(+), 21 deletions(-) diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx index 51c2e635..8080f389 100644 --- a/src/components/Roof2.jsx +++ b/src/components/Roof2.jsx @@ -2,7 +2,6 @@ import { useCanvas } from '@/hooks/useCanvas' import { useEffect, useState } from 'react' import { Mode, useMode } from '@/hooks/useMode' import { Button } from '@nextui-org/react' - import RangeSlider from './ui/RangeSlider' import { useRecoilState, useRecoilValue } from 'recoil' import { canvasSizeState, fontSizeState, roofMaterialState, sortedPolygonArray, templateTypeState, compassState } from '@/store/canvasAtom' @@ -10,6 +9,8 @@ import { QLine } from '@/components/fabric/QLine' import { getCanvasState, insertCanvasState } from '@/lib/canvas' import { calculateIntersection } from '@/util/canvas-util' import { QPolygon } from '@/components/fabric/QPolygon' +import * as turf from '@turf/turf' +import { toGeoJSON } from '@/util/qpolygon-utils' export default function Roof2() { const { canvas, handleRedo, handleUndo, setCanvasBackgroundWithDots, saveImage, addCanvas } = useCanvas('canvas') @@ -53,6 +54,7 @@ export default function Roof2() { makeRoofPatternPolygon, createRoofRack, drawRoofPolygon, + drawCellInTrestle, } = useMode() // const [canvasState, setCanvasState] = useRecoilState(canvasAtom) @@ -615,7 +617,10 @@ export default function Roof2() { 지붕타입 지붕재 + )} diff --git a/src/hooks/useCanvas.js b/src/hooks/useCanvas.js index f106ec5a..968f3676 100644 --- a/src/hooks/useCanvas.js +++ b/src/hooks/useCanvas.js @@ -89,8 +89,8 @@ export function useCanvas(id) { canvas?.off('object:modified') canvas?.off('object:removed') canvas?.off('object:added') - canvas?.off('mouse:move', drawMouseLines) - canvas?.off('mouse:down', handleMouseDown) + canvas?.off('mouse:move') + canvas?.off('mouse:down') } const addEventOnObject = (e) => { @@ -112,9 +112,11 @@ export function useCanvas(id) { target.on('mousedown', () => { if (target.get('selected')) { target.set({ strokeWidth: 1 }) + target.set({ strokeDashArray: [5, 5] }) target.set({ selected: false }) } else { target.set({ strokeWidth: 5 }) + target.set({ strokeDashArray: [0, 0] }) target.set({ selected: true }) } canvas?.renderAll() diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index 3d48e63e..72f45c9e 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -537,6 +537,7 @@ export function useMode() { if (historyPoints.current.length >= 4) { const wall = drawWallPolygon() + setWall(wall) handleOuterlinesTest2(wall) setTemplateType(1) } @@ -4460,13 +4461,18 @@ export function useMode() { } const createRoofRack = () => { + const trestlePolygons = canvas?.getObjects().filter((obj) => obj.name === 'trestle') + // 이미 만들어진 가대가 있을 경우 return + if (trestlePolygons.length !== 0) { + return + } + + canvas?.off('mouse:move') + canvas?.off('mouse:out') + document.removeEventListener('keydown', handleKeyDown) const roofs = canvas?.getObjects().filter((obj) => obj.name === 'roof') let roofCells = [] // roof에 적재된 cell들 roofs.forEach((roof, index) => { - let maxLengthLine = roof.lines.reduce((acc, cur) => { - return acc.length > cur.length ? acc : cur - }) - const offsetPolygonPoint = offsetPolygon(roof.points, -20) const trestlePoly = new QPolygon(offsetPolygonPoint, { @@ -4487,24 +4493,47 @@ export function useMode() { }) canvas?.add(trestlePoly) - - let drawRoofCells - if (maxLengthLine.direction === 'right' || maxLengthLine.direction === 'left') { - drawRoofCells = trestlePoly.fillCell({ width: 100, height: 50, padding: 10 }) - trestlePoly.direction = 'south' - } else { - drawRoofCells = trestlePoly.fillCell({ width: 50, height: 100, padding: 10 }) - trestlePoly.direction = 'east' - } - - drawRoofCells.forEach((cell) => { - roofCells.push(cell) - }) }) setDrewRoofCells(roofCells) } + //배터리 셀 넣기 + const drawCellInTrestle = () => { + const trestlePolygons = canvas?.getObjects().filter((obj) => obj.name === 'trestle' && obj.selected) + const notSelectedTrestlePolygons = canvas?.getObjects().filter((obj) => obj.name === 'trestle' && !obj.selected) + if (trestlePolygons.length === 0) { + alert('가대가 없습니다.') + } + + if (notSelectedTrestlePolygons.length > 0) { + alert('기존 셀은 제거됩니다.') + } + + notSelectedTrestlePolygons.forEach((trestle) => { + trestle.cells.forEach((cell) => { + canvas?.remove(cell) + }) + }) + + const drawCellsArray = [] + trestlePolygons.forEach((trestle, index) => { + trestle.fire('mousedown') + let maxLengthLine = trestle.lines.reduce((acc, cur) => { + return acc.length > cur.length ? acc : cur + }) + + let drawRoofCells + if (maxLengthLine.direction === 'right' || maxLengthLine.direction === 'left') { + drawRoofCells = trestle.fillCell({ width: 50, height: 100, padding: 0 }) + trestle.direction = 'south' + } else { + drawRoofCells = trestle.fillCell({ width: 100, height: 50, padding: 0 }) + trestle.direction = 'east' + } + }) + } + // 외적을 계산하는 함수 const crossProduct = (p1, p2, p3) => { const dx1 = p2.x - p1.x @@ -4547,5 +4576,6 @@ export function useMode() { makeRoofTrestle, createRoofRack, drawRoofPolygon, + drawCellInTrestle, } } From a7ffc17eb9baf5aecbcf3e9a3fd5c282cc322231 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 9 Aug 2024 16:20:51 +0900 Subject: [PATCH 2/4] =?UTF-8?q?=EB=AA=A8=EC=9E=84=EC=A7=80=EB=B6=95=20?= =?UTF-8?q?=EB=8B=A8=EA=B3=84=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/qpolygon-utils.js | 72 +++++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 8 deletions(-) diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 258f5d97..f6162e54 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -9,6 +9,7 @@ import { getRoofHypotenuse, } from '@/util/canvas-util' import { QPolygon } from '@/components/fabric/QPolygon' +import * as turf from '@turf/turf' const TWO_PI = Math.PI * 2 @@ -983,6 +984,43 @@ export const splitPolygonWithLines = (polygon) => { }) }) + /** + * 좌표 테스트용 + */ + allLines.forEach((line) => { + const text = new fabric.Text(`(${line.startPoint.x},${line.startPoint.y})`, { + left: line.startPoint.x, + top: line.startPoint.y, + fontSize: 15, + }) + + polygon.canvas.add(text) + polygon.canvas.renderAll() + + const text2 = new fabric.Text(`(${line.endPoint.x},${line.endPoint.y})`, { + left: line.endPoint.x, + top: line.endPoint.y, + fontSize: 15, + }) + + polygon.canvas.add(text2) + polygon.canvas.renderAll() + }) + + polygon.points.forEach((point, index) => { + const text = new fabric.Text(`(${point.x},${point.y})`, { + left: point.x, + top: point.y, + fontSize: 15, + }) + + polygon.canvas.add(text) + polygon.canvas.renderAll() + }) + /** + * 좌표 테스트용 끝 + */ + polygon.points.forEach((point, index) => { allLines.forEach((line) => { if (line.endPoint.x === point.x && line.endPoint.y === point.y) { @@ -1007,22 +1045,39 @@ export const splitPolygonWithLines = (polygon) => { const arrivalPoint = endLine.endPoint routes.push(startLine.startPoint) routes.push(startLine.endPoint) + //hip끼리 만나는 경우는 아무것도 안해도됨 - let count = 0 if (!isSamePoint(startLine.endPoint, arrivalPoint)) { // polygon line까지 추가 const allLinesCopy = [...allLines, ...polygon.lines] // hip이 만나지 않는 경우 갈 수 있는 길을 다 돌아야함 let currentPoint = startLine.endPoint let currentLine = startLine - - while (!isSamePoint(currentPoint, arrivalPoint) && count <= polygon.points.length) { - count++ + let movedLines = [] + let subMovedLines = [] + while (!isSamePoint(currentPoint, arrivalPoint)) { // startHip에서 만나는 출발선 두개. 두개의 선을 출발하여 arrivalPoint에 도착할 때 까지 count를 세고, 더 낮은 count를 가진 길을 선택한다. let connectedLines = allLinesCopy.filter((line) => isSamePoint(line.startPoint, currentPoint) || isSamePoint(line.endPoint, currentPoint)) connectedLines = connectedLines.filter((line) => line !== currentLine) + connectedLines = connectedLines.filter((line) => !subMovedLines.includes(line)) + + //마지막 선이 endLine의 startPoint와 같은경우 그 전까지 movedLine을 제거한다. + const endLineMeetLineCnt = connectedLines.filter((line) => { + return isSamePoint(line.endPoint, endLine.startPoint) || isSamePoint(line.startPoint, endLine.startPoint) + }).length + + if (endLineMeetLineCnt !== 0) { + movedLines.push(subMovedLines) + + console.log(movedLines, index) + } + + connectedLines = connectedLines.filter((line) => { + return !isSamePoint(line.endPoint, endLine.startPoint) && !isSamePoint(line.startPoint, endLine.startPoint) + }) + if (connectedLines.length === 0) { return } @@ -1050,14 +1105,15 @@ export const splitPolygonWithLines = (polygon) => { currentPoint = tempPoints[minIndex].point currentLine = tempPoints[minIndex].line + if (currentLine !== startLine) { + subMovedLines.push(currentLine) + } routes.push(currentPoint) } } - if (count <= polygon.points.length - 1) { - routes.push(endLine.startPoint) - roofs.push(routes) - } + routes.push(endLine.startPoint) + roofs.push(routes) }) // 중복 제거 From 6458b508947a8ea3d3376b4babf3122fe300b6d7 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 9 Aug 2024 16:50:32 +0900 Subject: [PATCH 3/4] =?UTF-8?q?=EB=AA=A8=EC=9E=84=EC=A7=80=EB=B6=95=20sele?= =?UTF-8?q?ctable=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useMode.js | 8 ++++++-- src/util/qpolygon-utils.js | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index 72f45c9e..c6c3552b 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -4480,7 +4480,7 @@ export function useMode() { stroke: 'red', strokeDashArray: [5, 5], strokeWidth: 1, - selectable: true, + selectable: false, fontSize: fontSize, name: 'trestle', lockMovementX: true, // X 축 이동 잠금 @@ -4504,9 +4504,10 @@ export function useMode() { const notSelectedTrestlePolygons = canvas?.getObjects().filter((obj) => obj.name === 'trestle' && !obj.selected) if (trestlePolygons.length === 0) { alert('가대가 없습니다.') + return } - if (notSelectedTrestlePolygons.length > 0) { + if (drewRoofCells.length > 0) { alert('기존 셀은 제거됩니다.') } @@ -4531,7 +4532,10 @@ export function useMode() { drawRoofCells = trestle.fillCell({ width: 100, height: 50, padding: 0 }) trestle.direction = 'east' } + drawCellsArray.push(drawRoofCells) }) + + setDrewRoofCells(drawCellsArray) } // 외적을 계산하는 함수 diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index f6162e54..5a216524 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1134,6 +1134,7 @@ export const splitPolygonWithLines = (polygon) => { fill: 'transparent', strokeWidth: 3, name: 'roof', + selectable: false, }) polygon.canvas.add(roof) From 89b6289e4ddd011f24be3dd073fd66bcd69413fe Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 9 Aug 2024 17:21:47 +0900 Subject: [PATCH 4/4] =?UTF-8?q?=EA=B0=80=EB=8C=80=20=EC=85=80=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useMode.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index c6c3552b..e00d5e5c 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -4515,6 +4515,7 @@ export function useMode() { trestle.cells.forEach((cell) => { canvas?.remove(cell) }) + trestle.cells = [] }) const drawCellsArray = []