Merge branch 'dev' into dev-yj

# Conflicts:
#	src/hooks/useMode.js
This commit is contained in:
yjnoh 2024-08-09 17:29:47 +09:00
commit 02635033ae
4 changed files with 123 additions and 21 deletions

View File

@ -2,7 +2,6 @@ import { useCanvas } from '@/hooks/useCanvas'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { Mode, useMode } from '@/hooks/useMode' import { Mode, useMode } from '@/hooks/useMode'
import { Button } from '@nextui-org/react' import { Button } from '@nextui-org/react'
import RangeSlider from './ui/RangeSlider' import RangeSlider from './ui/RangeSlider'
import { useRecoilState, useRecoilValue } from 'recoil' import { useRecoilState, useRecoilValue } from 'recoil'
import { canvasSizeState, fontSizeState, roofMaterialState, sortedPolygonArray, templateTypeState, compassState } from '@/store/canvasAtom' 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 { getCanvasState, insertCanvasState } from '@/lib/canvas'
import { calculateIntersection } from '@/util/canvas-util' import { calculateIntersection } from '@/util/canvas-util'
import { QPolygon } from '@/components/fabric/QPolygon' import { QPolygon } from '@/components/fabric/QPolygon'
import * as turf from '@turf/turf'
import { toGeoJSON } from '@/util/qpolygon-utils'
export default function Roof2() { export default function Roof2() {
const { canvas, handleRedo, handleUndo, setCanvasBackgroundWithDots, saveImage, addCanvas } = useCanvas('canvas') const { canvas, handleRedo, handleUndo, setCanvasBackgroundWithDots, saveImage, addCanvas } = useCanvas('canvas')
@ -53,6 +54,7 @@ export default function Roof2() {
makeRoofPatternPolygon, makeRoofPatternPolygon,
createRoofRack, createRoofRack,
drawRoofPolygon, drawRoofPolygon,
drawCellInTrestle,
} = useMode() } = useMode()
// const [canvasState, setCanvasState] = useRecoilState(canvasAtom) // const [canvasState, setCanvasState] = useRecoilState(canvasAtom)
@ -618,7 +620,10 @@ export default function Roof2() {
지붕타입 지붕재 지붕타입 지붕재
</Button> </Button>
<Button className="m-1 p-2" onClick={createRoofRack}> <Button className="m-1 p-2" onClick={createRoofRack}>
지붕가대 지붕가대설치
</Button>
<Button className="m-1 p-2" onClick={drawCellInTrestle}>
선택한 가대 셀채우기
</Button> </Button>
</> </>
)} )}

View File

@ -89,8 +89,8 @@ export function useCanvas(id) {
canvas?.off('object:modified') canvas?.off('object:modified')
canvas?.off('object:removed') canvas?.off('object:removed')
canvas?.off('object:added') canvas?.off('object:added')
canvas?.off('mouse:move', drawMouseLines) canvas?.off('mouse:move')
canvas?.off('mouse:down', handleMouseDown) canvas?.off('mouse:down')
} }
const addEventOnObject = (e) => { const addEventOnObject = (e) => {
@ -112,9 +112,11 @@ export function useCanvas(id) {
target.on('mousedown', () => { target.on('mousedown', () => {
if (target.get('selected')) { if (target.get('selected')) {
target.set({ strokeWidth: 1 }) target.set({ strokeWidth: 1 })
target.set({ strokeDashArray: [5, 5] })
target.set({ selected: false }) target.set({ selected: false })
} else { } else {
target.set({ strokeWidth: 5 }) target.set({ strokeWidth: 5 })
target.set({ strokeDashArray: [0, 0] })
target.set({ selected: true }) target.set({ selected: true })
} }
canvas?.renderAll() canvas?.renderAll()

View File

@ -541,6 +541,7 @@ export function useMode() {
if (historyPoints.current.length >= 4) { if (historyPoints.current.length >= 4) {
const wall = drawWallPolygon() const wall = drawWallPolygon()
setWall(wall)
handleOuterlinesTest2(wall) handleOuterlinesTest2(wall)
setTemplateType(1) setTemplateType(1)
} }
@ -4464,13 +4465,18 @@ export function useMode() {
} }
const createRoofRack = () => { 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') const roofs = canvas?.getObjects().filter((obj) => obj.name === 'roof')
let roofCells = [] // roof에 적재된 cell들 let roofCells = [] // roof에 적재된 cell들
roofs.forEach((roof, index) => { 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 offsetPolygonPoint = offsetPolygon(roof.points, -20)
const trestlePoly = new QPolygon(offsetPolygonPoint, { const trestlePoly = new QPolygon(offsetPolygonPoint, {
@ -4478,7 +4484,7 @@ export function useMode() {
stroke: 'red', stroke: 'red',
strokeDashArray: [5, 5], strokeDashArray: [5, 5],
strokeWidth: 1, strokeWidth: 1,
selectable: true, selectable: false,
fontSize: fontSize, fontSize: fontSize,
name: 'trestle', name: 'trestle',
lockMovementX: true, // X 축 이동 잠금 lockMovementX: true, // X 축 이동 잠금
@ -4491,14 +4497,45 @@ export function useMode() {
}) })
canvas?.add(trestlePoly) 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 let drawRoofCells
if (maxLengthLine.direction === 'right' || maxLengthLine.direction === 'left') { if (maxLengthLine.direction === 'right' || maxLengthLine.direction === 'left') {
drawRoofCells = trestlePoly.fillCell({ width: 100, height: 50, padding: 10 }) drawRoofCells = trestle.fillCell({ width: 50, height: 100, padding: 0 })
trestlePoly.direction = 'south' trestle.direction = 'south'
} else { } else {
drawRoofCells = trestlePoly.fillCell({ width: 50, height: 100, padding: 10 }) drawRoofCells = trestle.fillCell({ width: 100, height: 50, padding: 0 })
trestlePoly.direction = 'east' trestle.direction = 'east'
} }
drawRoofCells.forEach((cell) => { drawRoofCells.forEach((cell) => {
@ -4589,5 +4626,6 @@ export function useMode() {
makeRoofTrestle, makeRoofTrestle,
createRoofRack, createRoofRack,
drawRoofPolygon, drawRoofPolygon,
drawCellInTrestle,
} }
} }

View File

@ -9,6 +9,7 @@ import {
getRoofHypotenuse, getRoofHypotenuse,
} from '@/util/canvas-util' } from '@/util/canvas-util'
import { QPolygon } from '@/components/fabric/QPolygon' import { QPolygon } from '@/components/fabric/QPolygon'
import * as turf from '@turf/turf'
const TWO_PI = Math.PI * 2 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) => { polygon.points.forEach((point, index) => {
allLines.forEach((line) => { allLines.forEach((line) => {
if (line.endPoint.x === point.x && line.endPoint.y === point.y) { if (line.endPoint.x === point.x && line.endPoint.y === point.y) {
@ -1007,22 +1045,39 @@ export const splitPolygonWithLines = (polygon) => {
const arrivalPoint = endLine.endPoint const arrivalPoint = endLine.endPoint
routes.push(startLine.startPoint) routes.push(startLine.startPoint)
routes.push(startLine.endPoint) routes.push(startLine.endPoint)
//hip끼리 만나는 경우는 아무것도 안해도됨 //hip끼리 만나는 경우는 아무것도 안해도됨
let count = 0
if (!isSamePoint(startLine.endPoint, arrivalPoint)) { if (!isSamePoint(startLine.endPoint, arrivalPoint)) {
// polygon line까지 추가 // polygon line까지 추가
const allLinesCopy = [...allLines, ...polygon.lines] const allLinesCopy = [...allLines, ...polygon.lines]
// hip이 만나지 않는 경우 갈 수 있는 길을 다 돌아야함 // hip이 만나지 않는 경우 갈 수 있는 길을 다 돌아야함
let currentPoint = startLine.endPoint let currentPoint = startLine.endPoint
let currentLine = startLine let currentLine = startLine
let movedLines = []
while (!isSamePoint(currentPoint, arrivalPoint) && count <= polygon.points.length) { let subMovedLines = []
count++ while (!isSamePoint(currentPoint, arrivalPoint)) {
// startHip에서 만나는 출발선 두개. 두개의 선을 출발하여 arrivalPoint에 도착할 때 까지 count를 세고, 더 낮은 count를 가진 길을 선택한다. // startHip에서 만나는 출발선 두개. 두개의 선을 출발하여 arrivalPoint에 도착할 때 까지 count를 세고, 더 낮은 count를 가진 길을 선택한다.
let connectedLines = allLinesCopy.filter((line) => isSamePoint(line.startPoint, currentPoint) || isSamePoint(line.endPoint, currentPoint)) let connectedLines = allLinesCopy.filter((line) => isSamePoint(line.startPoint, currentPoint) || isSamePoint(line.endPoint, currentPoint))
connectedLines = connectedLines.filter((line) => line !== currentLine) 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) { if (connectedLines.length === 0) {
return return
} }
@ -1050,14 +1105,15 @@ export const splitPolygonWithLines = (polygon) => {
currentPoint = tempPoints[minIndex].point currentPoint = tempPoints[minIndex].point
currentLine = tempPoints[minIndex].line currentLine = tempPoints[minIndex].line
if (currentLine !== startLine) {
subMovedLines.push(currentLine)
}
routes.push(currentPoint) routes.push(currentPoint)
} }
} }
if (count <= polygon.points.length - 1) { routes.push(endLine.startPoint)
routes.push(endLine.startPoint) roofs.push(routes)
roofs.push(routes)
}
}) })
// 중복 제거 // 중복 제거
@ -1078,6 +1134,7 @@ export const splitPolygonWithLines = (polygon) => {
fill: 'transparent', fill: 'transparent',
strokeWidth: 3, strokeWidth: 3,
name: 'roof', name: 'roof',
selectable: false,
}) })
polygon.canvas.add(roof) polygon.canvas.add(roof)