From 86d9e574bb4e699c0483005288c0b2e78744ad34 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Mon, 11 Nov 2024 10:19:40 +0900 Subject: [PATCH] =?UTF-8?q?=EC=84=A0=EC=86=8D=EC=84=B1=20=EC=9E=91?= =?UTF-8?q?=EC=97=85=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/common.js | 1 + .../flowDirection/FlowDirectionSetting.jsx | 26 +-- .../lineProperty/LinePropertySetting.jsx | 21 ++- src/hooks/surface/useSurfaceShapeBatch.js | 178 ++++++++++++++++-- src/hooks/useContextMenu.js | 9 +- src/locales/ko.json | 4 + 6 files changed, 210 insertions(+), 29 deletions(-) diff --git a/src/common/common.js b/src/common/common.js index d0016af1..eb86bb89 100644 --- a/src/common/common.js +++ b/src/common/common.js @@ -161,6 +161,7 @@ export const SAVE_KEY = [ 'groupId', 'planeSize', 'actualSize', + 'surfaceId', ] export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype] diff --git a/src/components/floor-plan/modal/flowDirection/FlowDirectionSetting.jsx b/src/components/floor-plan/modal/flowDirection/FlowDirectionSetting.jsx index 8e54c646..effb4717 100644 --- a/src/components/floor-plan/modal/flowDirection/FlowDirectionSetting.jsx +++ b/src/components/floor-plan/modal/flowDirection/FlowDirectionSetting.jsx @@ -5,14 +5,18 @@ import { useRecoilValue } from 'recoil' import { contextPopupPositionState } from '@/store/popupAtom' import { useMessage } from '@/hooks/useMessage' import { usePopup } from '@/hooks/usePopup' - +import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch' export default function FlowDirectionSetting(props) { const contextPopupPosition = useRecoilValue(contextPopupPositionState) const { id, pos = contextPopupPosition, target } = props const { getMessage } = useMessage() const { closePopup } = usePopup() const [compasDeg, setCompasDeg] = useState(360) + const [flowDirection, setFlowDirection] = useState(target.direction) + const { changeSurfaceFlowDirection } = useSurfaceShapeBatch() + const orientations = [ + // { name: `${getMessage('commons.none')}`, value: 0 }, { name: `${getMessage('commons.south')}`, value: 360 }, { name: `${getMessage('commons.south')}${getMessage('commons.east')}`, value: 315 }, { name: `${getMessage('commons.south')}${getMessage('commons.west')}`, value: 45 }, @@ -75,13 +79,13 @@ export default function FlowDirectionSetting(props) {
{getMessage('commons.north')} - + {getMessage('commons.east')} - + {getMessage('commons.south')} - + {getMessage('commons.west')} - +
@@ -111,18 +115,14 @@ export default function FlowDirectionSetting(props) { key={index} className={`circle ${compasDeg === 15 * (12 + index) ? 'act' : ''}`} onClick={() => setCompasDeg(15 * (12 + index))} - > - {13 - index} - + > ))} {Array.from({ length: 180 / 15 - 1 }).map((dot, index) => (
setCompasDeg(15 * (index + 1))} - > - {24 - index} -
+ > ))}
@@ -133,7 +133,9 @@ export default function FlowDirectionSetting(props) {
- +
diff --git a/src/components/floor-plan/modal/lineProperty/LinePropertySetting.jsx b/src/components/floor-plan/modal/lineProperty/LinePropertySetting.jsx index f5425e67..5b4075f0 100644 --- a/src/components/floor-plan/modal/lineProperty/LinePropertySetting.jsx +++ b/src/components/floor-plan/modal/lineProperty/LinePropertySetting.jsx @@ -3,13 +3,18 @@ import { useRecoilValue } from 'recoil' import { contextPopupPositionState } from '@/store/popupAtom' import { useMessage } from '@/hooks/useMessage' import { usePopup } from '@/hooks/usePopup' -import { useState } from 'react' +import { useState, useEffect } from 'react' +import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch' +import { useEvent } from '@/hooks/useEvent' export default function LinePropertySetting(props) { const contextPopupPosition = useRecoilValue(contextPopupPositionState) - const { id, pos = contextPopupPosition } = props + const { id, pos = contextPopupPosition, target } = props const { getMessage } = useMessage() const { closePopup } = usePopup() + const { changeSurfaceLinePropertyEvent, changeSurfaceLineProperty } = useSurfaceShapeBatch() + const { initEvent } = useEvent() + const properties = [ { name: getMessage('eaves.line'), value: 'eaves' }, { name: getMessage('ridge'), value: 'ridge' }, @@ -29,6 +34,14 @@ export default function LinePropertySetting(props) { { name: getMessage('no.setting'), value: 'noSetting' }, ] const [selectedProperty, setSelectedProperty] = useState(null) + + useEffect(() => { + changeSurfaceLinePropertyEvent(target) + return () => { + initEvent() + } + }, []) + return (
@@ -66,7 +79,9 @@ export default function LinePropertySetting(props) {
- +
diff --git a/src/hooks/surface/useSurfaceShapeBatch.js b/src/hooks/surface/useSurfaceShapeBatch.js index d2c6aee7..67ee1874 100644 --- a/src/hooks/surface/useSurfaceShapeBatch.js +++ b/src/hooks/surface/useSurfaceShapeBatch.js @@ -13,6 +13,8 @@ import { usePopup } from '@/hooks/usePopup' import { roofDisplaySelector } from '@/store/settingAtom' import { usePolygon } from '@/hooks/usePolygon' import { fontSelector } from '@/store/fontAtom' +import { slopeSelector } from '@/store/commonAtom' +import { QLine } from '@/components/fabric/QLine' export function useSurfaceShapeBatch() { const { getMessage } = useMessage() @@ -22,6 +24,7 @@ export function useSurfaceShapeBatch() { const canvas = useRecoilValue(canvasState) const globalPitch = useRecoilValue(globalPitchState) const roofDisplay = useRecoilValue(roofDisplaySelector) + const slope = useRecoilValue(slopeSelector(globalPitch)) const { swalFire } = useSwal() const { addCanvasMouseEventListener, initEvent } = useEvent() const { closePopup } = usePopup() @@ -126,6 +129,7 @@ export function useSurfaceShapeBatch() { addCanvasMouseEventListener('mouse:down', (e) => { isDrawing = false obj.set('name', POLYGON_TYPE.ROOF) + obj.set('surfaceId', surfaceId) initEvent() setSurfaceShapePattern(obj, roofDisplay.column) closePopup(id) @@ -580,18 +584,19 @@ export function useSurfaceShapeBatch() { text: '배치면 내용을 전부 삭제하시겠습니까?', type: 'confirm', confirmFn: () => { - canvas?.getObjects().forEach((obj) => { - if ( - obj.name === POLYGON_TYPE.ROOF || - obj.name === BATCH_TYPE.OPENING || - obj.name === BATCH_TYPE.SHADOW || - obj.name === BATCH_TYPE.TRIANGLE_DORMER || - obj.name === BATCH_TYPE.PENTAGON_DORMER || - obj.name === 'lengthText' - ) { - canvas?.remove(obj) - } - }) + // canvas?.getObjects().forEach((obj) => { + // if ( + // obj.name === POLYGON_TYPE.ROOF || + // obj.name === BATCH_TYPE.OPENING || + // obj.name === BATCH_TYPE.SHADOW || + // obj.name === BATCH_TYPE.TRIANGLE_DORMER || + // obj.name === BATCH_TYPE.PENTAGON_DORMER || + // obj.name === 'lengthText' + // ) { + // canvas?.remove(obj) + // } + // }) + canvas.clear() swalFire({ text: '삭제 완료 되었습니다.' }) }, // denyFn: () => { @@ -823,10 +828,159 @@ export function useSurfaceShapeBatch() { canvas.renderAll() } + const surfaceShapeActualSize = () => { + const roofs = canvas.getObjects().filter((obj) => obj.name === 'roof') + let notParallelLines = [] + + const roofArray = [] + + roofs.forEach((obj) => { + const roof = { + id: obj.id, + surfaceId: obj.surfaceId, + targetLines: [], + baseLines: [], + direction: obj.direction, + } + obj.lines.forEach((line) => { + if (obj.direction === 'north' || obj.direction === 'south') { + if (line.y1 !== line.y2) { + roof.targetLines.push(line) + } else { + roof.baseLines.push(line) + } + } else { + if (line.x1 !== line.x2) { + roof.targetLines.push(line) + } else { + roof.baseLines.push(line) + } + } + }) + roofArray.push(roof) + }) + + const slopeRadians = slope.angleValue * (Math.PI / 180) + const tanSlope = Math.tan(slopeRadians) + + roofArray.forEach((roof) => { + roof.targetLines.forEach((line) => { + let calcLength = line.length + + if (roof.surfaceId === 1) { + calcLength = roof.direction === 'north' || roof.direction === 'south' ? Math.abs(line.y1 - line.y2) : Math.abs(line.x1 - line.x2) + } + + const h = calcLength * tanSlope + const resultLength = Math.sqrt(Math.pow(calcLength, 2) + Math.pow(h, 2)) + + line.set({ + attributes: { + ...line.attributes, + actualSize: parseInt((Math.floor(resultLength) * 10).toFixed(0)), + planeSize: parseInt(line.length * 10), + }, + }) + }) + roof.baseLines.forEach((line) => { + line.set({ + attributes: { + ...line.attributes, + actualSize: parseInt((Math.floor(line.length) * 10).toFixed(0)), + planeSize: parseInt(line.length * 10), + }, + }) + }) + }) + } + + const changeSurfaceLinePropertyEvent = (roof) => { + let tmpLines = [] + roof.set({ + selectable: false, + }) + canvas.discardActiveObject() + roof.lines.forEach((obj, index) => { + const tmpLine = new QLine([obj.x1, obj.y1, obj.x2, obj.y2], { + ...obj, + stroke: 'rgb(3, 255, 0)', + strokeWidth: 8, + selectable: true, + name: 'lineProperty', + index: index, + }) + + tmpLines.push(tmpLine) + canvas.add(tmpLine) + }) + + addCanvasMouseEventListener('mouse:down', (e) => { + const selectedLine = e.target + if (selectedLine) { + selectedLine.set({ + stroke: 'red', + name: 'selectedLineProperty', + }) + tmpLines.forEach((line) => { + if (line.index !== selectedLine.index) { + line.set({ + stroke: 'rgb(3, 255, 0)', + name: 'lineProperty', + }) + } + }) + } else { + tmpLines.forEach((line) => { + line.set({ + stroke: 'rgb(3, 255, 0)', + name: 'lineProperty', + }) + }) + } + }) + + canvas.renderAll() + } + + const changeSurfaceLineProperty = (property) => { + console.log(property) + if (!property) { + swalFire({ text: getMessage('modal.line.property.change'), icon: 'error' }) + return + } + + const selectedLine = canvas.getActiveObjects() + if (selectedLine && selectedLine[0].name === 'selectedLineProperty') { + swalFire({ + text: getMessage('modal.line.property.change.confirm'), + type: 'confirm', + confirmFn: () => { + selectedLine.set({ + type: property.value, + }) + }, + }) + } else { + swalFire({ text: getMessage('modal.line.property.change.unselect'), icon: 'error' }) + } + } + + const changeSurfaceFlowDirection = (roof, direction, orientation) => { + roof.set({ + direction: direction, + }) + drawDirectionArrow(roof) + canvas?.renderAll() + } + return { applySurfaceShape, deleteAllSurfacesAndObjects, moveSurfaceShapeBatch, resizeSurfaceShapeBatch, + surfaceShapeActualSize, + changeSurfaceFlowDirection, + changeSurfaceLinePropertyEvent, + changeSurfaceLineProperty, } } diff --git a/src/hooks/useContextMenu.js b/src/hooks/useContextMenu.js index 64892dce..cc8cce69 100644 --- a/src/hooks/useContextMenu.js +++ b/src/hooks/useContextMenu.js @@ -51,7 +51,7 @@ export function useContextMenu() { const [column, setColumn] = useState(null) const { handleZoomClear } = useCanvasEvent() const { moveObjectBatch } = useObjectBatch({}) - const { moveSurfaceShapeBatch } = useSurfaceShapeBatch() + const { moveSurfaceShapeBatch, surfaceShapeActualSize } = useSurfaceShapeBatch() const currentMenuSetting = () => { switch (currentMenu) { case MENU.PLAN_DRAWING: @@ -303,6 +303,11 @@ export function useContextMenu() { case 'roof': setContextMenu([ [ + { + id: 'surfaceShapeActualSize', + name: '면형상 실측', + fn: () => surfaceShapeActualSize(), + }, { id: 'sizeEdit', name: '사이즈 변경', @@ -336,7 +341,7 @@ export function useContextMenu() { { id: 'linePropertyEdit', name: getMessage('contextmenu.line.property.edit'), - component: , + component: , }, { id: 'flowDirectionEdit', diff --git a/src/locales/ko.json b/src/locales/ko.json index a2ef69b3..bfa3cdc5 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -400,6 +400,9 @@ "modal.module.circuit.number.edit": "모듈 일괄 회로 번호 변경", "modal.module.circuit.number.edit.info": "회로 번호를 입력해주세요.", "modal.module.circuit.number": "회로 번호", + "modal.line.property.change": "변경할 속성을 선택해 주세요.", + "modal.line.property.change.unselect": "변경할 라인을 선택해 주세요.", + "modal.line.property.change.confirm": "속성을 변경하시겠습니까?", "common.message.no.data": "No data", "common.message.no.dataDown": "No data to download", "common.message.noData": "No data to display", @@ -495,6 +498,7 @@ "commons.east": "동", "commons.south": "남", "commons.north": "북", + "commons.none": "선택안함", "font.style.normal": "보통", "font.style.italic": "기울임꼴", "font.style.bold": "굵게",