From 9faba60fd64a96ae43ab0a766a712db7095757b3 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Thu, 23 Jan 2025 11:01:07 +0900 Subject: [PATCH] =?UTF-8?q?=EB=AA=A8=EB=93=88=20=EB=B0=B0=EC=B9=98?= =?UTF-8?q?=EB=A9=B4=20=EC=B2=98=EB=A7=88=EB=A9=B4=20=EC=9D=B8=ED=84=B0?= =?UTF-8?q?=EB=B2=8C=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../floor-plan/modal/basic/step/Placement.jsx | 1 - src/hooks/module/useModuleBasicSetting.js | 157 +------------- src/hooks/module/useModulePlace.js | 201 +++++++++++++++--- 3 files changed, 183 insertions(+), 176 deletions(-) diff --git a/src/components/floor-plan/modal/basic/step/Placement.jsx b/src/components/floor-plan/modal/basic/step/Placement.jsx index ff1eeb35..9a53a1c0 100644 --- a/src/components/floor-plan/modal/basic/step/Placement.jsx +++ b/src/components/floor-plan/modal/basic/step/Placement.jsx @@ -24,7 +24,6 @@ const Placement = forwardRef((props, refs) => { //모듈 배치면 생성 useEffect(() => { - makeModuleInstArea() if (moduleSelectionData) { //1개라도 치도리 불가가 있으면 치도리 불가 const isChidroriValue = moduleSelectionData.roofConstructions.some((item) => item.construction.plvrYn === 'N') diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index f9b8a7fe..bc0569d3 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -1,5 +1,5 @@ import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' -import { canvasState, checkedModuleState, isManualModuleSetupState, selectedModuleState } from '@/store/canvasAtom' +import { canvasSettingState, canvasState, checkedModuleState, isManualModuleSetupState, selectedModuleState } from '@/store/canvasAtom' import { rectToPolygon, polygonToTurfPolygon, calculateVisibleModuleHeight, getDegreeByChon } from '@/util/canvas-util' import { basicSettingState, roofDisplaySelector } from '@/store/settingAtom' import offsetPolygon, { calculateAngle } from '@/util/qpolygon-utils' @@ -8,9 +8,7 @@ import { moduleSetupSurfaceState, moduleIsSetupState } from '@/store/canvasAtom' import { useEvent } from '@/hooks/useEvent' import { POLYGON_TYPE, BATCH_TYPE } from '@/common/common' import * as turf from '@turf/turf' -import { v4 as uuidv4 } from 'uuid' import { useSwal } from '@/hooks/useSwal' -import { canvasSettingState } from '@/store/canvasAtom' import { compasDegAtom } from '@/store/orientationAtom' import { QLine } from '@/components/fabric/QLine' import { useRoofFn } from '@/hooks/common/useRoofFn' @@ -24,9 +22,9 @@ export function useModuleBasicSetting() { const roofDisplay = useRecoilValue(roofDisplaySelector) const [moduleSetupSurface, setModuleSetupSurface] = useRecoilState(moduleSetupSurfaceState) const [moduleIsSetup, setModuleIsSetup] = useRecoilState(moduleIsSetupState) - const { addTargetMouseEventListener, addCanvasMouseEventListener, initEvent, removeMouseEvent } = useEvent() + const { addCanvasMouseEventListener, initEvent, removeMouseEvent } = useEvent() const { swalFire } = useSwal() - const canvasSetting = useRecoilValue(canvasSettingState) + const compasDeg = useRecoilValue(compasDegAtom) const { setSurfaceShapePattern } = useRoofFn() const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState) @@ -34,6 +32,8 @@ export function useModuleBasicSetting() { const [isManualModuleSetup, setIsManualModuleSetup] = useRecoilState(isManualModuleSetupState) const setModuleStatistics = useSetRecoilState(moduleStatisticsState) + const canvasSetting = useRecoilValue(canvasSettingState) + useEffect(() => { // console.log('basicSetting', basicSetting) if (canvas) { @@ -46,7 +46,6 @@ export function useModuleBasicSetting() { }, []) // const { addTargetMouseEventListener, addCanvasMouseEventListener, initEvent } = useContext(EventContext) - let selectedModuleInstSurfaceArray = [] //모듈,회로에서 다른메뉴 -> 배치면으로 갈 경수 초기화 const restoreModuleInstArea = () => { @@ -71,149 +70,6 @@ export function useModuleBasicSetting() { }) } - const makeModuleInstArea = () => { - //지붕 객체 반환 - - const roofs = canvas.getObjects().filter((obj) => obj.name === 'roof') - let offsetLength = canvasSetting.roofSizeSet === 3 ? -90 : -20 - - if (!roofs) { - return - } - - const batchObjects = canvas - ?.getObjects() - .filter( - (obj) => - obj.name === BATCH_TYPE.OPENING || - obj.name === BATCH_TYPE.SHADOW || - obj.name === BATCH_TYPE.TRIANGLE_DORMER || - obj.name === BATCH_TYPE.PENTAGON_DORMER, - ) //도머s 객체 - - //도머도 외곽을 따야한다 - - const batchObjectOptions = { - stroke: 'red', - fill: 'transparent', - strokeDashArray: [10, 4], - strokeWidth: 1, - lockMovementX: true, - lockMovementY: true, - lockRotation: true, - lockScalingX: true, - lockScalingY: true, - selectable: true, - name: POLYGON_TYPE.OBJECT_SURFACE, - originX: 'center', - originY: 'center', - } - - batchObjects.forEach((obj) => { - if (obj.name === BATCH_TYPE.TRIANGLE_DORMER || obj.name === BATCH_TYPE.PENTAGON_DORMER) { - const groupPoints = obj.groupPoints - const offsetObjects = offsetPolygon(groupPoints, 10) - const dormerOffset = new QPolygon(offsetObjects, batchObjectOptions) - dormerOffset.setViewLengthText(false) - canvas.add(dormerOffset) //모듈설치면 만들기 - } else { - const points = obj.points - const offsetObjects = offsetPolygon(points, 10) - const offset = new QPolygon(offsetObjects, batchObjectOptions) - offset.setViewLengthText(false) - canvas.add(offset) //모듈설치면 만들기 - } - }) - - roofs.forEach((roof) => { - const isExistSurface = canvas.getObjects().find((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.parentId === roof.id) - if (isExistSurface) { - return - } - - setSurfaceShapePattern(roof, roofDisplay.column, true) //패턴 변경 - const offsetPoints = offsetPolygon(roof.points, offsetLength) //안쪽 offset - //모듈설치영역?? 생성 - - const surfaceId = uuidv4() - - let setupSurface = new QPolygon(offsetPoints, { - stroke: 'red', - fill: 'transparent', - strokeDashArray: [10, 4], - strokeWidth: 1, - lockMovementX: true, - lockMovementY: true, - lockRotation: true, - lockScalingX: true, - lockScalingY: true, - selectable: true, - parentId: roof.id, //가대 폴리곤의 임시 인덱스를 넣어줌 - name: POLYGON_TYPE.MODULE_SETUP_SURFACE, - flowDirection: roof.direction, - direction: roof.direction, - flipX: roof.flipX, - flipY: roof.flipY, - surfaceId: surfaceId, - originX: 'center', - originY: 'center', - modules: [], - roofMaterial: roof.roofMaterial, - // angle: -compasDeg, - }) - - setupSurface.setViewLengthText(false) - canvas.add(setupSurface) //모듈설치면 만들기 - - //지붕면 선택 금지 - roof.set({ - selectable: false, - }) - - //모듈설치면 클릭이벤트 - addTargetMouseEventListener('mousedown', setupSurface, function () { - toggleSelection(setupSurface) - }) - }) - } - - //설치 범위 지정 클릭 이벤트 - const toggleSelection = (setupSurface) => { - const isExist = selectedModuleInstSurfaceArray.some((obj) => obj.parentId === setupSurface.parentId) - //최초 선택일때 - if (!isExist) { - //기본 선택이랑 스트로크 굵기가 같으면 선택 안됨으로 봄 - setupSurface.set({ - ...setupSurface, - strokeWidth: 3, - strokeDashArray: [0], - fill: 'transparent', - }) - canvas.discardActiveObject() // 객체의 활성 상태 해제 - //중복으로 들어가는걸 방지하기 위한 코드 - - canvas?.renderAll() - selectedModuleInstSurfaceArray.push(setupSurface) - } else { - //선택후 재선택하면 선택안됨으로 변경 - setupSurface.set({ - ...setupSurface, - fill: 'transparent', - strokeDashArray: [10, 4], - strokeWidth: 1, - }) - canvas.discardActiveObject() // 객체의 활성 상태 해제 - - //폴리곤에 커스텀 인덱스를 가지고 해당 배열 인덱스를 찾아 삭제함 - const removeIndex = setupSurface.parentId - const removeArrayIndex = selectedModuleInstSurfaceArray.findIndex((obj) => obj.parentId === removeIndex) - selectedModuleInstSurfaceArray.splice(removeArrayIndex, 1) - } - - canvas?.renderAll() - setModuleSetupSurface([...selectedModuleInstSurfaceArray]) - } - /** * trestle에서 영역을 가져와 mouse:move 이벤트로 해당 영역에 진입했을때 booleanPointInPolygon 로 진입여부를 확인 * 확인 후 셀을 이동시킴 @@ -1131,6 +987,8 @@ export function useModuleBasicSetting() { const flowDirection = moduleSetupSurface.flowDirection + console.log('moduleSetupSurface', moduleSetupSurface) + let intvHor = flowDirection === 'south' || flowDirection === 'north' ? moduleSetupSurface.trestleDetail.moduleIntvlHor @@ -2349,7 +2207,6 @@ export function useModuleBasicSetting() { } return { - makeModuleInstArea, manualModuleSetup, autoModuleSetup, restoreModuleInstArea, diff --git a/src/hooks/module/useModulePlace.js b/src/hooks/module/useModulePlace.js index 5a25a50a..0af46cf9 100644 --- a/src/hooks/module/useModulePlace.js +++ b/src/hooks/module/useModulePlace.js @@ -1,17 +1,28 @@ import { useEffect, useState } from 'react' -import { useRecoilState, useRecoilValue } from 'recoil' +import { useRecoilValue, useSetRecoilState } from 'recoil' import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions' import { useMasterController } from '@/hooks/common/useMasterController' -import { canvasState, currentCanvasPlanState } from '@/store/canvasAtom' +import { canvasSettingState, canvasState, currentCanvasPlanState, moduleSetupSurfaceState } from '@/store/canvasAtom' +import { POLYGON_TYPE, BATCH_TYPE } from '@/common/common' +import { useRoofFn } from '@/hooks/common/useRoofFn' +import { roofDisplaySelector } from '@/store/settingAtom' +import offsetPolygon from '@/util/qpolygon-utils' +import { v4 as uuidv4 } from 'uuid' +import { QPolygon } from '@/components/fabric/QPolygon' +import { useEvent } from '@/hooks/useEvent' export function useModulePlace() { const canvas = useRecoilValue(canvasState) const moduleSelectionData = useRecoilValue(moduleSelectionDataState) - const currentCanvasPlan = useRecoilValue(currentCanvasPlanState) const [trestleDetailParams, setTrestleDetailParams] = useState([]) const [trestleDetailList, setTrestleDetailList] = useState([]) const selectedModules = useRecoilValue(selectedModuleState) const { getTrestleDetailList } = useMasterController() + const canvasSetting = useRecoilValue(canvasSettingState) + const { setSurfaceShapePattern } = useRoofFn() + const roofDisplay = useRecoilValue(roofDisplaySelector) + const { addTargetMouseEventListener } = useEvent() + const setModuleSetupSurface = useSetRecoilState(moduleSetupSurfaceState) useEffect(() => { if (moduleSelectionData) { @@ -40,7 +51,9 @@ export function useModulePlace() { const getTrestleDetailListData = async () => { const trestleDetailList = await getTrestleDetailList(trestleDetailParams) - setTrestleDetailList(trestleDetailList) + if (trestleDetailList.length > 0) { + setTrestleDetailList(trestleDetailList) + } } useEffect(() => { @@ -50,30 +63,168 @@ export function useModulePlace() { }, [trestleDetailParams]) useEffect(() => { - //지붕을 가져옴 - console.log('🚀 ~ trestleDetailList.forEach ~ trestleDetailList:', trestleDetailList) - canvas - .getObjects() - .filter((roof) => roof.name === 'roof') - .forEach((roof) => { - const roofIndex = roof.roofMaterial.index //지붕의 지붕재의 순번 - trestleDetailList.forEach((detail) => { - if (Number(detail.data.roofIndex) === roofIndex) { - //roof에 상세 데이터 추가 - roof.set({ trestleDetail: detail.data }) - - //surface에 상세 데이터 추가 - canvas - .getObjects() - .filter((surface) => surface.name === 'moduleSetupSurface' && surface.parentId === roof.id) - .forEach((surface) => { - surface.set({ trestleDetail: detail.data, roofMaterial: roof.roofMaterial }) - }) - } + if (trestleDetailList.length > 0) { + //지붕을 가져옴 + canvas + .getObjects() + .filter((roof) => roof.name === 'roof') + .forEach((roof) => { + const roofIndex = roof.roofMaterial.index //지붕의 지붕재의 순번 + trestleDetailList.forEach((detail) => { + if (Number(detail.data.roofIndex) === roofIndex) { + //roof에 상세 데이터 추가 + roof.set({ trestleDetail: detail.data }) + //배치면 설치 영역 + makeModuleInstArea(roof, detail.data) + //surface에 상세 데이터 추가 + } + }) }) - }) + } }, [trestleDetailList]) + const makeModuleInstArea = (roof, trestleDetail) => { + //지붕 객체 반환 + + if (!roof) { + return + } + + const batchObjects = canvas + ?.getObjects() + .filter( + (obj) => + obj.name === BATCH_TYPE.OPENING || + obj.name === BATCH_TYPE.SHADOW || + obj.name === BATCH_TYPE.TRIANGLE_DORMER || + obj.name === BATCH_TYPE.PENTAGON_DORMER, + ) //도머s 객체 + + //도머도 외곽을 따야한다 + + const batchObjectOptions = { + stroke: 'red', + fill: 'transparent', + strokeDashArray: [10, 4], + strokeWidth: 1, + lockMovementX: true, + lockMovementY: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, + selectable: true, + name: POLYGON_TYPE.OBJECT_SURFACE, + originX: 'center', + originY: 'center', + } + + batchObjects.forEach((obj) => { + if (obj.name === BATCH_TYPE.TRIANGLE_DORMER || obj.name === BATCH_TYPE.PENTAGON_DORMER) { + const groupPoints = obj.groupPoints + const offsetObjects = offsetPolygon(groupPoints, 10) + const dormerOffset = new QPolygon(offsetObjects, batchObjectOptions) + dormerOffset.setViewLengthText(false) + canvas.add(dormerOffset) //모듈설치면 만들기 + } else { + const points = obj.points + const offsetObjects = offsetPolygon(points, 10) + const offset = new QPolygon(offsetObjects, batchObjectOptions) + offset.setViewLengthText(false) + canvas.add(offset) //모듈설치면 만들기 + } + }) + + const isExistSurface = canvas.getObjects().find((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.parentId === roof.id) + if (isExistSurface) { + return + } + + let offsetLength = canvasSetting.roofSizeSet === 3 ? -90 : (trestleDetail.eaveIntvl / 10) * -1 + setSurfaceShapePattern(roof, roofDisplay.column, true) //패턴 변경 + const offsetPoints = offsetPolygon(roof.points, offsetLength) //안쪽 offset + //모듈설치영역?? 생성 + + const surfaceId = uuidv4() + + let setupSurface = new QPolygon(offsetPoints, { + stroke: 'red', + fill: 'transparent', + strokeDashArray: [10, 4], + strokeWidth: 1, + lockMovementX: true, + lockMovementY: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, + selectable: true, + parentId: roof.id, //가대 폴리곤의 임시 인덱스를 넣어줌 + name: POLYGON_TYPE.MODULE_SETUP_SURFACE, + flowDirection: roof.direction, + direction: roof.direction, + flipX: roof.flipX, + flipY: roof.flipY, + surfaceId: surfaceId, + originX: 'center', + originY: 'center', + modules: [], + roofMaterial: roof.roofMaterial, + trestleDetail: trestleDetail, + // angle: -compasDeg, + }) + + setupSurface.setViewLengthText(false) + canvas.add(setupSurface) //모듈설치면 만들기 + + //지붕면 선택 금지 + roof.set({ + selectable: false, + }) + + //모듈설치면 클릭이벤트 + addTargetMouseEventListener('mousedown', setupSurface, function () { + toggleSelection(setupSurface) + }) + } + + let selectedModuleInstSurfaceArray = [] + + //설치 범위 지정 클릭 이벤트 + const toggleSelection = (setupSurface) => { + const isExist = selectedModuleInstSurfaceArray.some((obj) => obj.parentId === setupSurface.parentId) + //최초 선택일때 + if (!isExist) { + //기본 선택이랑 스트로크 굵기가 같으면 선택 안됨으로 봄 + setupSurface.set({ + ...setupSurface, + strokeWidth: 3, + strokeDashArray: [0], + fill: 'transparent', + }) + canvas.discardActiveObject() // 객체의 활성 상태 해제 + //중복으로 들어가는걸 방지하기 위한 코드 + + canvas?.renderAll() + selectedModuleInstSurfaceArray.push(setupSurface) + } else { + //선택후 재선택하면 선택안됨으로 변경 + setupSurface.set({ + ...setupSurface, + fill: 'transparent', + strokeDashArray: [10, 4], + strokeWidth: 1, + }) + canvas.discardActiveObject() // 객체의 활성 상태 해제 + + //폴리곤에 커스텀 인덱스를 가지고 해당 배열 인덱스를 찾아 삭제함 + const removeIndex = setupSurface.parentId + const removeArrayIndex = selectedModuleInstSurfaceArray.findIndex((obj) => obj.parentId === removeIndex) + selectedModuleInstSurfaceArray.splice(removeArrayIndex, 1) + } + + canvas?.renderAll() + setModuleSetupSurface([...selectedModuleInstSurfaceArray]) + } + return { selectedModules, }