diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx index 39f15c7a..20883410 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) @@ -618,7 +620,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 05ecbfde..9edd121c 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -541,6 +541,7 @@ export function useMode() { if (historyPoints.current.length >= 4) { const wall = drawWallPolygon() + setWall(wall) handleOuterlinesTest2(wall) setTemplateType(1) } @@ -4464,13 +4465,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, { @@ -4478,7 +4484,7 @@ export function useMode() { stroke: 'red', strokeDashArray: [5, 5], strokeWidth: 1, - selectable: true, + selectable: false, fontSize: fontSize, name: 'trestle', lockMovementX: true, // X 축 이동 잠금 @@ -4491,14 +4497,45 @@ export function useMode() { }) canvas?.add(trestlePoly) + }) + + 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('가대가 없습니다.') + return + } + + if (drewRoofCells.length > 0) { + alert('기존 셀은 제거됩니다.') + } + + notSelectedTrestlePolygons.forEach((trestle) => { + trestle.cells.forEach((cell) => { + canvas?.remove(cell) + }) + trestle.cells = [] + }) + + 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 = trestlePoly.fillCell({ width: 100, height: 50, padding: 10 }) - trestlePoly.direction = 'south' + drawRoofCells = trestle.fillCell({ width: 50, height: 100, padding: 0 }) + trestle.direction = 'south' } else { - drawRoofCells = trestlePoly.fillCell({ width: 50, height: 100, padding: 10 }) - trestlePoly.direction = 'east' + drawRoofCells = trestle.fillCell({ width: 100, height: 50, padding: 0 }) + trestle.direction = 'east' } drawRoofCells.forEach((cell) => { @@ -4589,5 +4626,6 @@ export function useMode() { makeRoofTrestle, createRoofRack, drawRoofPolygon, + drawCellInTrestle, } } diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 258f5d97..5a216524 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) }) // 중복 제거 @@ -1078,6 +1134,7 @@ export const splitPolygonWithLines = (polygon) => { fill: 'transparent', strokeWidth: 3, name: 'roof', + selectable: false, }) polygon.canvas.add(roof)