From 3d266b21d7fec8318f60d5d6761ed59d9f5facba Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Mon, 12 Aug 2024 17:42:55 +0900 Subject: [PATCH] =?UTF-8?q?=EB=B3=B4=EC=A1=B0=EC=84=A0=20=EC=97=B0?= =?UTF-8?q?=EA=B2=B0=EB=AA=A8=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Roof2.jsx | 36 ++- src/hooks/useCanvas.js | 5 +- src/hooks/useMode.js | 550 +++++++++++++++++-------------------- src/util/common-utils.js | 11 + src/util/qpolygon-utils.js | 3 +- 5 files changed, 297 insertions(+), 308 deletions(-) create mode 100644 src/util/common-utils.js diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx index 20883410..68303710 100644 --- a/src/components/Roof2.jsx +++ b/src/components/Roof2.jsx @@ -4,13 +4,20 @@ 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' +import { + canvasSizeState, + compassState, + fontSizeState, + roofMaterialState, + roofState, + sortedPolygonArray, + templateTypeState, + wallState, +} from '@/store/canvasAtom' 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') @@ -38,6 +45,10 @@ export default function Roof2() { const [compass, setCompass] = useRecoilState(compassState) + const roof = useRecoilValue(roofState) + + const wall = useRecoilValue(wallState) + const { mode, setMode, @@ -55,6 +66,8 @@ export default function Roof2() { createRoofRack, drawRoofPolygon, drawCellInTrestle, + setDirectionTrestles, + cutHelpLines, } = useMode() // const [canvasState, setCanvasState] = useRecoilState(canvasAtom) @@ -553,12 +566,19 @@ export default function Roof2() { - {/* + */} + @@ -614,6 +634,9 @@ export default function Roof2() { */} + {templateType === 1 && ( <> + diff --git a/src/hooks/useCanvas.js b/src/hooks/useCanvas.js index 968f3676..27c80187 100644 --- a/src/hooks/useCanvas.js +++ b/src/hooks/useCanvas.js @@ -1,6 +1,6 @@ import { useEffect, useRef, useState } from 'react' import { fabric } from 'fabric' -import { actionHandler, anchorWrapper, polygonPositionHandler } from '@/util/canvas-util' +import { actionHandler, anchorWrapper, calculateIntersection, distanceBetweenPoints, polygonPositionHandler } from '@/util/canvas-util' import { useRecoilState } from 'recoil' import { canvasSizeState, fontSizeState } from '@/store/canvasAtom' @@ -9,6 +9,8 @@ import { QPolygon } from '@/components/fabric/QPolygon' import { defineQLine } from '@/util/qline-utils' import { defineQPloygon } from '@/util/qpolygon-utils' +import * as turf from '@turf/turf' + export function useCanvas(id) { const [canvas, setCanvas] = useState() const [isLocked, setIsLocked] = useState(false) @@ -65,6 +67,7 @@ export function useCanvas(id) { initialize() canvas?.on('object:added', onChange) canvas?.on('object:added', addEventOnObject) + canvas?.on('object:modified', onChange) canvas?.on('object:removed', onChange) canvas?.on('mouse:move', drawMouseLines) diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index 9edd121c..968c76ca 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -1,5 +1,13 @@ import { useEffect, useRef, useState } from 'react' -import { findTopTwoIndexesByDistance, getCenterPoint, getDirection, getStartIndex, rearrangeArray } from '@/util/canvas-util' +import { + calculateIntersection, + distanceBetweenPoints, + findTopTwoIndexesByDistance, + getCenterPoint, + getDirection, + getStartIndex, + rearrangeArray, +} from '@/util/canvas-util' import { useRecoilState, useRecoilValue } from 'recoil' import { @@ -18,6 +26,8 @@ import { QLine } from '@/components/fabric/QLine' import { fabric } from 'fabric' import { QPolygon } from '@/components/fabric/QPolygon' import offsetPolygon from '@/util/qpolygon-utils' +import { isObjectNotEmpty } from '@/util/common-utils' +import * as turf from '@turf/turf' export const Mode = { DRAW_LINE: 'drawLine', // 기준선 긋기모드` @@ -31,6 +41,7 @@ export const Mode = { ROOF_TRESTLE: 'roofTrestle', //지붕가대 모드 FILL_CELLS: 'fillCells', //태양광셀 모드 CELL_POWERCON: 'cellPowercon', //파워콘 + DRAW_HELP_LINE: 'drawHelpLine', // 보조선 그리기 모드 지붕 존재해야함 DEFAULT: 'default', } @@ -254,6 +265,14 @@ export function useMode() { case 'cellPowercon': makeCellPowercon() break + case 'drawHelpLine': + canvas?.off('selection:created', addSelectCreatedEvent) + canvas?.off('selection:cleared', addSelectClearedEvent) + canvas?.on('selection:created', addSelectCreatedEvent) + canvas?.on('selection:cleared', addSelectClearedEvent) + drawHelpLineMode() + break + case 'default': canvas?.off('mouse:down') break @@ -340,6 +359,81 @@ export function useMode() { canvas?.renderAll() } + const addSelectCreatedEvent = (e) => { + const target = e.selected[0] + + if (target.name === 'helpPoint') { + canvas?.on('mouse:move', helpPointEvent.mouseMove) + } + } + + const helpPointEvent = { + mouseMove: (e) => { + const target = canvas?.getActiveObject() + const pointer = canvas?.getPointer(e.e) + const point = { x: target.left + target.radius, y: target.top + target.radius } + const angle = Math.atan2(pointer.y - point.y, pointer.x - point.x) + const degree = fabric.util.radiansToDegrees(angle) + + const min = [0, 45, 90, -0, -90, -45, 135, -135, 180, -180].reduce((prev, curr) => { + return Math.abs(curr - degree) < Math.abs(prev - degree) ? curr : prev + }) + + // Calculate the center point of the target object + const centerX = target.left + target.width / 2 + const centerY = target.top + target.height / 2 + + const length = distanceBetweenPoints(point, { x: pointer.x, y: pointer.y }) + + // min의 각도와 pointer의 위치를 이용하여 새로운 점을 구한다. + const newPoint = { + x: centerX + length * Math.cos(fabric.util.degreesToRadians(min)), + y: centerY + length * Math.sin(fabric.util.degreesToRadians(min)), + } + + const line = new fabric.Line([point.x, point.y, newPoint.x, newPoint.y], { + stroke: 'black', + strokeWidth: 1, + selectable: false, + name: 'beforeHelpLine', + helpPoint: target, + }) + + const helpLines = canvas?._objects.filter((obj) => obj.name === 'beforeHelpLine') + helpLines.forEach((item) => canvas?.remove(item)) + + canvas?.add(line) + }, + } + + const addSelectClearedEvent = (e) => { + const target = e.deselected[0] + + if (target.name === 'helpPoint') { + const beforeHelpLines = canvas?._objects.filter((obj) => obj.name === 'beforeHelpLine' && obj.helpPoint === target) + + const helpLines = canvas?._objects.filter((obj) => obj.name === 'helpLine' && obj.helpPoint === target) + + beforeHelpLines.forEach((item) => canvas?.remove(item)) + helpLines.forEach((item) => canvas?.remove(item)) + + const newPoint = { x: beforeHelpLines[0].x2, y: beforeHelpLines[0].y2 } + + const helpLine = new fabric.Line([target.left + target.radius, target.top + target.radius, newPoint.x, newPoint.y], { + stroke: 'red', + strokeWidth: 1, + selectable: false, + name: 'helpLine', + helpPoint: target, + }) + + canvas?.add(helpLine) + canvas?.renderAll() + + canvas?.off('mouse:move', helpPointEvent.mouseMove) + } + } + const handleKeyDown = (e) => { switch (e.key) { case 'ArrowDown': { @@ -531,7 +625,7 @@ export function useMode() { // handleOuterlines() const wall = makePolygon(null, sort) wall.set({ name: 'wall' }) - setWall(wall) + console.log('wall', wall) return wall } @@ -695,6 +789,7 @@ export function useMode() { viewLengthText: true, fontSize: fontSize, sort: sort, + selectable: false, }, canvas, ) @@ -738,296 +833,6 @@ export function useMode() { setZoom(Math.ceil(zoom - 10)) } - const handleOuterlines = () => { - const newOuterlines = [] - for (let i = 0; i < historyLines.current.length; i++) { - const next = historyLines.current[i + 1] - const prev = historyLines.current[i - 1] ?? historyLines.current[historyLines.current.length - 1] - if (next) { - if (next.direction === 'right') { - // 다름 라인이 오른쪽으로 이동 - if (historyLines.current[i].direction === 'top') { - if (prev.direction !== 'right') { - if (historyLines.current.length === 4) { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 - 50, - }) - } else if (historyLines.current.length === 6) { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 - 50, - }) - } else if (historyLines.current.length === 8) { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 + 50, - }) - } - } else { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 + 50, - }) - } - } else { - // bottom - if (prev?.direction !== 'right') { - if (historyLines.current.length === 4) { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 + 50, - }) - } else if (historyLines.current.length === 6) { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 + 50, - }) - } else if (historyLines.current.length === 8) { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 - 50, - }) - } - } else { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 + 50, - }) - } - } - } else if (next.direction === 'left') { - if (historyLines.current[i].direction === 'top') { - if (prev?.direction !== 'left') { - if (historyLines.current.length === 4) { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 - 50, - }) - } else if (historyLines.current.length === 6) { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 - 50, - }) - } else if (historyLines.current.length === 8) { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 + 50, - }) - } - } else { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 - 50, - }) - } - } else { - // bottom - if (prev?.direction !== 'left') { - if (historyLines.current.length === 4) { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 + 50, - }) - } else if (historyLines.current.length === 6) { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 + 50, - }) - } else if (historyLines.current.length === 8) { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 - 50, - }) - } - } else { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 - 50, - }) - } - } - } else if (next.direction === 'top') { - if (historyLines.current[i].direction === 'right') { - if (prev?.direction !== 'top') { - if (historyLines.current.length === 4) { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 + 50, - }) - } else if (historyLines.current.length === 6) { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 + 50, - }) - } else if (historyLines.current.length === 8) { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 - 50, - }) - } - } else { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 + 50, - }) - } - } else { - // left - if (prev?.direction !== 'top') { - if (historyLines.current.length === 4) { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 + 50, - }) - } else if (historyLines.current.length === 6) { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 + 50, - }) - } else if (historyLines.current.length === 8) { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 - 50, - }) - } - } else { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 - 50, - }) - } - } - } else if (next.direction === 'bottom') { - if (historyLines.current[i].direction === 'right') { - if (prev?.direction !== 'bottom') { - if (historyLines.current.length === 4) { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 - 50, - }) - } else if (historyLines.current.length === 6) { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 - 50, - }) - } else if (historyLines.current.length === 8) { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 + 50, - }) - } - } else { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 + 50, - }) - } - } else { - // left - if (prev.direction !== 'bottom') { - if (historyLines.current.length === 4) { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 - 50, - }) - } else if (historyLines.current.length === 6) { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 - 50, - }) - } else if (historyLines.current.length === 8) { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 + 50, - }) - } - } else { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 - 50, - }) - } - } - } - } else { - const tmp = newOuterlines[newOuterlines.length - 1] - newOuterlines.push({ - x1: tmp.x2, - y1: tmp.y2, - x2: newOuterlines[0].x1, - y2: newOuterlines[0].y1, - }) - } - } - - makePolygon(newOuterlines) - } - /** *벽 지붕 외곽선 생성 */ @@ -1115,9 +920,10 @@ export function useMode() { ) roof.setWall(polygon) setRoof(roof) + setWall(polygon) - roof.drawHelpLine() - roof.divideLine() + // roof.drawHelpLine() + // roof.divideLine() } const drawRoofPolygon = (wall, offset = 50) => { @@ -4465,6 +4271,7 @@ export function useMode() { } const createRoofRack = () => { + roof.divideLine() const trestlePolygons = canvas?.getObjects().filter((obj) => obj.name === 'trestle') // 이미 만들어진 가대가 있을 경우 return if (trestlePolygons.length !== 0) { @@ -4475,7 +4282,6 @@ export function useMode() { 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) => { const offsetPolygonPoint = offsetPolygon(roof.points, -20) @@ -4498,8 +4304,6 @@ export function useMode() { canvas?.add(trestlePoly) }) - - setDrewRoofCells(roofCells) } //배터리 셀 넣기 @@ -4531,19 +4335,24 @@ export function useMode() { let drawRoofCells if (maxLengthLine.direction === 'right' || maxLengthLine.direction === 'left') { - drawRoofCells = trestle.fillCell({ width: 50, height: 100, padding: 0 }) + drawRoofCells = trestle.fillCell({ width: 50, height: 100, padding: 10 }) trestle.direction = 'south' } else { - drawRoofCells = trestle.fillCell({ width: 100, height: 50, padding: 0 }) + drawRoofCells = trestle.fillCell({ width: 100, height: 50, padding: 10 }) trestle.direction = 'east' } drawRoofCells.forEach((cell) => { - roofCells.push(cell) + drawCellsArray.push(cell) }) }) - setDrewRoofCells(roofCells) + setDrewRoofCells(drawCellsArray) + } + + // 가대 방위 설정 + const setDirectionTrestles = () => { + console.log('roof', roof) } const makeCellPowercon = () => { @@ -4610,6 +4419,143 @@ export function useMode() { return { concaveIndices: concaveIndices, concavePointIndices: concavePointIndices } } + const drawHelpLineMode = () => { + if (!isObjectNotEmpty(roof)) { + alert('지붕을 먼저 그려주세요.') + setMode(Mode.DEFAULT) + return + } + + const roofPoints = roof.points + const wallPoints = wall.points + + roofPoints.forEach((roofPoint, index) => { + const circle = new fabric.Circle({ + radius: 5, + fill: 'red', + left: roofPoint.x - 5, + top: roofPoint.y - 5, + selectable: true, // 선택 가능하게 설정 + lockMovementX: true, // X 축 이동 잠금 + lockMovementY: true, // Y 축 이동 잠금 + lockRotation: true, // 회전 잠금 + lockScalingX: true, // X 축 크기 조정 잠금 + lockScalingY: true, // Y 축 크기 조정 잠금 + name: 'helpPoint', + }) + + canvas?.add(circle) + canvas?.renderAll() + }) + } + + const cutHelpLines = () => { + // 먼저 hip을 자른다. + canvas + ?.getObjects() + .filter((obj) => obj.name === 'helpLine') + .forEach((line, index1) => { + canvas + ?.getObjects() + .filter((obj) => obj.name === 'helpLine') + .forEach((line2, index2) => { + if (line === line2) { + return + } + + const intersectionPoint = calculateIntersection(line, line2) + if (!intersectionPoint) { + return + } + + canvas?.remove(line) + canvas?.remove(line2) + + const hip1 = new QLine([line.x1, line.y1, intersectionPoint.x, intersectionPoint.y], { + stroke: 'black', + strokeWidth: 1, + selectable: false, + name: 'hip', + }) + + const hip2 = new QLine([line2.x1, line2.y1, intersectionPoint.x, intersectionPoint.y], { + stroke: 'black', + strokeWidth: 1, + selectable: false, + name: 'hip', + }) + + const interSectionCircle = new fabric.Circle({ + radius: 5, + fill: 'red', + left: intersectionPoint.x - 5, + top: intersectionPoint.y - 5, + selectable: true, // 선택 가능하게 설정 + lockMovementX: true, // X 축 이동 잠금 + lockMovementY: true, // Y 축 이동 잠금 + lockRotation: true, // 회전 잠금 + lockScalingX: true, // X 축 크기 조정 잠금 + lockScalingY: true, // Y 축 크기 조정 잠금 + name: 'helpPoint', + }) + + canvas?.add(hip1) + canvas?.add(hip2) + roof.innerLines.push(hip1) + roof.innerLines.push(hip2) + canvas?.add(interSectionCircle) + canvas?.renderAll() + }) + }) + + canvas + ?.getObjects() + .filter((obj) => obj.name === 'helpLine') + .forEach((line) => { + const helpPoints = canvas?.getObjects().filter((obj) => obj.name === 'helpPoint') + let cnt = 0 + let intersectionPoints = [] + helpPoints.forEach((point) => { + if (cnt === 2) { + return + } + if ( + turf.booleanPointOnLine( + turf.point([point.left + point.radius, point.top + point.radius]), + turf.lineString([ + [line.x1, line.y1], + [line.x2, line.y2], + ]), + ) + ) { + intersectionPoints.push(point) + cnt++ + } + }) + + if (intersectionPoints.length === 2) { + const ridge = new QLine( + [ + intersectionPoints[0].left + intersectionPoints[0].radius, + intersectionPoints[0].top + intersectionPoints[0].radius, + intersectionPoints[1].left + intersectionPoints[1].radius, + intersectionPoints[1].top + intersectionPoints[1].radius, + ], + { + stroke: 'black', + strokeWidth: 1, + selectable: false, + name: 'ridge', + }, + ) + roof.innerLines.push(ridge) + canvas?.add(ridge) + canvas?.remove(line) + canvas?.renderAll() + } + }) + } + return { mode, setMode, @@ -4627,5 +4573,7 @@ export function useMode() { createRoofRack, drawRoofPolygon, drawCellInTrestle, + setDirectionTrestles, + cutHelpLines, } } diff --git a/src/util/common-utils.js b/src/util/common-utils.js new file mode 100644 index 00000000..9f53fede --- /dev/null +++ b/src/util/common-utils.js @@ -0,0 +1,11 @@ +/** + * Check if an object is not empty. + * @param {Object} obj - The object to check. + * @returns {boolean} - Returns true if the object is not empty, false otherwise. + */ +export const isObjectNotEmpty = (obj) => { + if (!obj) { + return false + } + return Object.keys(obj).length > 0 +} diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 5a216524..77af0df5 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1127,7 +1127,7 @@ export const splitPolygonWithLines = (polygon) => { }) }) - roofs.forEach((roofPoint) => { + roofs.forEach((roofPoint, index) => { const roof = new QPolygon(roofPoint, { fontSize: polygon.fontSize, stroke: 'black', @@ -1135,6 +1135,7 @@ export const splitPolygonWithLines = (polygon) => { strokeWidth: 3, name: 'roof', selectable: false, + startDirection: polygon.lines[index].direction, }) polygon.canvas.add(roof)