From 80f2198af2b93ccc009d1ac7feab95b9bd29a2d2 Mon Sep 17 00:00:00 2001 From: changkyu choi Date: Thu, 12 Dec 2024 18:58:16 +0900 Subject: [PATCH 001/114] =?UTF-8?q?=EB=B0=B0=EC=B9=98=20API=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Playground.jsx | 64 ++++++++++++++++++- src/hooks/common/useMasterController.js | 82 ++++++++++++++++++++++--- 2 files changed, 137 insertions(+), 9 deletions(-) diff --git a/src/components/Playground.jsx b/src/components/Playground.jsx index e3d185ec..6646aac6 100644 --- a/src/components/Playground.jsx +++ b/src/components/Playground.jsx @@ -36,7 +36,7 @@ export default function Playground() { const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL const { getMessage } = useMessage() const { swalFire } = useSwal() - const { getRoofMaterialList, getModuleTypeItemList } = useMasterController() + const { getRoofMaterialList, getModuleTypeItemList, getTrestleList, getConstructionList, getTrestleDetailList } = useMasterController() const [color, setColor] = useState('#ff0000') @@ -154,6 +154,41 @@ export default function Playground() { console.log('users:', users) }, [users]) + const trestleData = [{ moduleTpCd: '1', roofMatlCd: '2', raftBaseCd: '', trestleMkrCd: '4', constMthdCd: '', roofBaseCd: '6' }] + const constructionData = [ + { + moduleTpCd: '', + roofMatlCd: '', + trestleMkrCd: '', + constMthdCd: '', + roofBaseCd: '', + illuminationTp: '', + instHt: '', + stdWindSpeed: '', + stdSnowLd: '', + inclCd: '', + raftBaseCd: '', + roofPitch: 0, + }, + ] + const trestleDetailData = [ + { + moduleTpCd: '', + roofMatlCd: '', + trestleMkrCd: '', + constMthdCd: '', + roofBaseCd: '', + illuminationTp: '', + instHt: '', + stdWindSpeed: '', + stdSnowLd: '', + inclCd: '', + constTp: '', + mixMatlNo: 0, + roofPitch: 0, + }, + ] + return ( <>
@@ -166,7 +201,7 @@ export default function Playground() { }} > 지붕재 목록 조회 API 호출 - + {' '} {' '} + {' '} + {' '} +
+
{plans.length < 10 && ( - )} diff --git a/src/hooks/useCanvasEvent.js b/src/hooks/useCanvasEvent.js index 0e8cd64b..7ea3e03c 100644 --- a/src/hooks/useCanvasEvent.js +++ b/src/hooks/useCanvasEvent.js @@ -3,7 +3,6 @@ import { useRecoilState, useRecoilValue } from 'recoil' import { v4 as uuidv4 } from 'uuid' import { canvasSizeState, canvasState, canvasZoomState, currentObjectState } from '@/store/canvasAtom' import { QPolygon } from '@/components/fabric/QPolygon' -import { usePlan } from '@/hooks/usePlan' import { fontSelector } from '@/store/fontAtom' // 캔버스에 필요한 이벤트 @@ -14,7 +13,6 @@ export function useCanvasEvent() { const canvasSize = useRecoilValue(canvasSizeState) const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState) const lengthTextOption = useRecoilValue(fontSelector('lengthText')) - const { modifiedPlanFlag, setModifiedPlanFlag } = usePlan() useEffect(() => { canvas?.setZoom(canvasZoom / 100) @@ -40,10 +38,6 @@ export function useCanvasEvent() { onChange: (e) => { const target = e.target - if (target.name !== 'mouseLine' && !modifiedPlanFlag) { - setModifiedPlanFlag((prev) => !prev) - } - if (target) { // settleDown(target) } @@ -58,10 +52,6 @@ export function useCanvasEvent() { target.uuid = uuidv4() } - if (target.name !== 'mouseLine' && !modifiedPlanFlag) { - setModifiedPlanFlag((prev) => !prev) - } - if (target.type === 'QPolygon' || target.type === 'QLine') { const textObjs = canvas?.getObjects().filter((obj) => obj.name === 'lengthText') textObjs.forEach((obj) => { @@ -164,9 +154,6 @@ export function useCanvasEvent() { target.on('moving', (e) => { target.uuid = uuidv4() - if (!modifiedPlanFlag) { - setModifiedPlanFlag((prev) => !prev) - } if (target.parentDirection === 'left' || target.parentDirection === 'right') { const minX = target.minX diff --git a/src/hooks/usePlan.js b/src/hooks/usePlan.js index 532759a4..b49d1eca 100644 --- a/src/hooks/usePlan.js +++ b/src/hooks/usePlan.js @@ -1,7 +1,7 @@ import { useEffect, useState } from 'react' import { useRecoilState } from 'recoil' import { v4 as uuidv4 } from 'uuid' -import { canvasState, currentCanvasPlanState, plansState, modifiedPlansState, modifiedPlanFlagState } from '@/store/canvasAtom' +import { canvasState, currentCanvasPlanState, plansState } from '@/store/canvasAtom' import { useAxios } from '@/hooks/useAxios' import { useMessage } from '@/hooks/useMessage' import { useSwal } from '@/hooks/useSwal' @@ -12,14 +12,11 @@ import { useCanvas } from '@/hooks/useCanvas' export function usePlan() { const [planNum, setPlanNum] = useState(0) const [selectedPlan, setSelectedPlan] = useState(null) - const [currentCanvasStatus, setCurrentCanvasStatus] = useState(null) const [canvas, setCanvas] = useRecoilState(canvasState) const [currentCanvasPlan, setCurrentCanvasPlan] = useRecoilState(currentCanvasPlanState) const [plans, setPlans] = useRecoilState(plansState) // 전체 plan - const [modifiedPlans, setModifiedPlans] = useRecoilState(modifiedPlansState) // 변경된 canvas plan - const [modifiedPlanFlag, setModifiedPlanFlag] = useRecoilState(modifiedPlanFlagState) // 캔버스 실시간 오브젝트 이벤트 감지 flag const { swalFire } = useSwal() const { getMessage } = useMessage() @@ -95,64 +92,6 @@ export function usePlan() { return addCanvas() } - /** - * 캔버스에서 발생하는 실시간 오브젝트 이벤트를 감지하여 수정 여부를 확인 후 관리 - */ - const checkCanvasObjectEvent = (planId) => { - setCurrentCanvasStatus(currentCanvasData()) - if (!modifiedPlans.some((modifiedPlan) => modifiedPlan === planId) && checkModifiedCanvasPlan(planId)) { - setModifiedPlans((prev) => [...prev, planId]) - setModifiedPlanFlag(false) - } - } - useEffect(() => { - if (currentCanvasStatus) { - setCurrentCanvasPlan((prev) => ({ ...prev, canvasStatus: currentCanvasStatus })) - } - }, [currentCanvasStatus]) - - /** - * 현재 캔버스 상태와 DB에 저장된 캔버스 상태를 비교하여 수정 여부를 판단 - */ - const checkModifiedCanvasPlan = (planId) => { - const planData = plans.find((plan) => plan.id === planId) - if (planData.canvasStatus === '') { - // 빈 상태로 저장된 캔버스 - return true - } - - // 각각 object들의 uuid 목록을 추출하여 비교 - const canvasStatus = currentCanvasData() - const canvasObjsUuids = getObjectUuids(JSON.parse(canvasStatus).objects) - const dbObjsUuids = getObjectUuids(JSON.parse(planData.canvasStatus).objects) - return canvasObjsUuids.length !== dbObjsUuids.length || !canvasObjsUuids.every((uuid, index) => uuid === dbObjsUuids[index]) - } - const getObjectUuids = (objects) => { - return objects - .filter((obj) => obj.hasOwnProperty('uuid')) - .map((obj) => obj.uuid) - .sort() - } - - const resetModifiedPlans = () => { - setModifiedPlans([]) - setModifiedPlanFlag(false) - } - - /** - * 캔버스에 저장되지 않은 변경사항이 있을때 저장 여부를 확인 후 저장 - */ - const checkUnsavedCanvasPlan = async () => { - swalFire({ - text: `Plan ${currentCanvasPlan.ordering} ` + getMessage('plan.message.confirm.save.modified'), - type: 'confirm', - confirmFn: async () => { - await putCanvasStatus(currentCanvasPlan.canvasStatus) - }, - }) - resetModifiedPlans() - } - /** * DB에 저장된 데이터를 canvas에서 사용할 수 있도록 포맷화 */ @@ -206,8 +145,8 @@ export function usePlan() { } await promisePost({ url: '/api/canvas-management/canvas-statuses', data: planData }) .then((res) => { - setPlans([...plans, { id: res.data, objectNo: objectNo, userId: userId, canvasStatus: canvasStatus, ordering: planNum + 1 }]) - handleCurrentPlan(res.data) + setPlans((plans) => [...plans, { id: res.data, objectNo: objectNo, userId: userId, canvasStatus: canvasStatus, ordering: planNum + 1 }]) + updateCurrentPlan(res.data) setPlanNum(planNum + 1) }) .catch((error) => { @@ -228,7 +167,6 @@ export function usePlan() { await promisePut({ url: '/api/canvas-management/canvas-statuses', data: planData }) .then((res) => { setPlans((plans) => plans.map((plan) => (plan.id === currentCanvasPlan.id ? { ...plan, canvasStatus: canvasStatus } : plan))) - setModifiedPlans((modifiedPlans) => modifiedPlans.filter((planId) => planId !== currentCanvasPlan.id)) }) .catch((error) => { swalFire({ text: error.message, icon: 'error' }) @@ -251,13 +189,11 @@ export function usePlan() { /** * plan 이동 - * 현재 plan의 작업상태를 확인, 저장 후 이동 + * 현재 plan의 작업상태를 저장 후 이동 */ const handleCurrentPlan = async (newCurrentId) => { if (!currentCanvasPlan || currentCanvasPlan.id !== newCurrentId) { - if (currentCanvasPlan?.id && modifiedPlans.some((modifiedPlan) => modifiedPlan === currentCanvasPlan.id)) { - await saveCanvas() - } + await saveCanvas() updateCurrentPlan(newCurrentId) } } @@ -281,9 +217,12 @@ export function usePlan() { /** * 새로운 plan 생성 - * 현재 plan의 데이터가 있을 경우 복제 여부를 확인 + * 현재 plan의 데이터가 있을 경우 현재 plan 저장 및 복제 여부를 확인 */ const handleAddPlan = async (userId, objectNo) => { + if (currentCanvasPlan?.id) { + await saveCanvas() + } JSON.parse(currentCanvasData()).objects.length > 0 ? swalFire({ text: `Plan ${currentCanvasPlan.ordering} ` + getMessage('plan.message.confirm.copy'), @@ -324,7 +263,6 @@ export function usePlan() { await delCanvasById(id) .then((res) => { setPlans((plans) => plans.filter((plan) => plan.id !== id)) - setModifiedPlans((modifiedPlans) => modifiedPlans.filter((planId) => planId !== currentCanvasPlan.id)) removeImage(currentCanvasPlan.id) swalFire({ text: getMessage('plan.message.delete') }) }) @@ -362,14 +300,6 @@ export function usePlan() { canvas, plans, selectedPlan, - currentCanvasPlan, - setCurrentCanvasPlan, - modifiedPlans, - modifiedPlanFlag, - setModifiedPlanFlag, - checkCanvasObjectEvent, - checkUnsavedCanvasPlan, - resetModifiedPlans, saveCanvas, handleCurrentPlan, handleAddPlan, diff --git a/src/locales/ja.json b/src/locales/ja.json index e0559649..ff40d26b 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -295,7 +295,6 @@ "modal.actual.size.setting.plane.size.length": "廊下の寸法の長さ", "modal.actual.size.setting.actual.size.length": "実寸長", "plan.message.confirm.save": "PLAN을 저장하시겠습니까?", - "plan.message.confirm.save.modified": "PLAN의 변경사항을 저장하시겠습니까?", "plan.message.confirm.copy": "PLAN을 복사하시겠습니까?", "plan.message.confirm.delete": "PLAN을 삭제하시겠습니까?", "plan.message.save": "저장되었습니다.", diff --git a/src/locales/ko.json b/src/locales/ko.json index b4b745bc..8260419f 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -300,7 +300,6 @@ "modal.actual.size.setting.plane.size.length": "복도치수 길이", "modal.actual.size.setting.actual.size.length": "실제치수 길이", "plan.message.confirm.save": "PLAN을 저장하시겠습니까?", - "plan.message.confirm.save.modified": "PLAN의 변경사항을 저장하시겠습니까?", "plan.message.confirm.copy": "PLAN을 복사하시겠습니까?", "plan.message.confirm.delete": "PLAN을 삭제하시겠습니까?", "plan.message.save": "저장되었습니다.", diff --git a/src/store/canvasAtom.js b/src/store/canvasAtom.js index b0e21d41..89f7e14d 100644 --- a/src/store/canvasAtom.js +++ b/src/store/canvasAtom.js @@ -272,17 +272,6 @@ export const plansState = atom({ default: [], }) -// 변경된 canvas plan 목록 -export const modifiedPlansState = atom({ - key: 'modifiedPlansState', - default: [], -}) -// 변경감지 flag -export const modifiedPlanFlagState = atom({ - key: 'modifiedPlanFlagState', - default: false, -}) - export const tempGridModeState = atom({ key: 'tempGridModeState', default: false, From 5bfee81dec774a4850051d9dadc04427532b8a98 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Fri, 13 Dec 2024 13:24:48 +0900 Subject: [PATCH 004/114] =?UTF-8?q?=EC=9C=A1=EC=A7=80=EB=B6=95=20=EC=A7=80?= =?UTF-8?q?=EB=B6=95=EB=A9=B4=20=EB=AA=A8=EB=93=88=20=EC=9E=91=EC=97=85?= =?UTF-8?q?=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modal/basic/step/pitch/PitchPlacement.jsx | 10 +- src/hooks/module/useModuleBasicSetting.js | 574 ++++++++++-------- 2 files changed, 330 insertions(+), 254 deletions(-) diff --git a/src/components/floor-plan/modal/basic/step/pitch/PitchPlacement.jsx b/src/components/floor-plan/modal/basic/step/pitch/PitchPlacement.jsx index d14bf0cc..51274ea3 100644 --- a/src/components/floor-plan/modal/basic/step/pitch/PitchPlacement.jsx +++ b/src/components/floor-plan/modal/basic/step/pitch/PitchPlacement.jsx @@ -9,16 +9,17 @@ import { useEvent } from '@/hooks/useEvent' const PitchPlacement = forwardRef((props, refs) => { const { getMessage } = useMessage() const [setupLocation, setSetupLocation] = useState('south') - const { makeModuleInstArea } = useModuleBasicSetting() + const { flatRoofMakeModuleInstArea } = useModuleBasicSetting() const canvas = useRecoilValue(canvasState) const { initEvent } = useEvent() useEffect(() => { - makeModuleInstArea() + flatRoofMakeModuleInstArea(setupLocation) }, []) useEffect(() => { handleChangeSetupLocation() + flatRoofMakeModuleInstArea(setupLocation) }, [setupLocation]) const moduleData = { @@ -56,11 +57,9 @@ const PitchPlacement = forwardRef((props, refs) => { return null } else { const moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴 + moduleSetupSurfaces.forEach((surface, index) => { - console.log(`surface ${index} : `, surface) - const excretaLine = surface.lines - excretaLine.forEach((line) => { line.set({ stroke: '#642EFB', @@ -74,6 +73,7 @@ const PitchPlacement = forwardRef((props, refs) => { excretaLine.forEach((obj) => obj.set({ stroke: '#642EFB', isSelected: false })) if (!line.isSelected) { line.set({ stroke: 'red', isSelected: true }) + surface.fire('mousedown') } else { line.set({ stroke: '#642EFB', isSelected: false }) } diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index e54b227f..6d8812e7 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -52,7 +52,7 @@ export function useModuleBasicSetting() { const makeModuleInstArea = () => { //지붕 객체 반환 const roofs = canvas.getObjects().filter((obj) => obj.name === 'roof') - let offsetLength = canvasSetting.roofSizeSet === 3 ? -90 : -20 + let offsetLength = -20 if (!roofs) { return @@ -105,7 +105,116 @@ export function useModuleBasicSetting() { } setupSurface.set({ flowLines: flowLines }) - flatRoofMakeSurface(roof, setupSurface) + + //지붕면 선택 금지 + roof.set({ + selectable: false, + }) + + //모듈설치면 클릭이벤트 + addTargetMouseEventListener('mousedown', setupSurface, function () { + toggleSelection(setupSurface) + }) + }) + } + + const flatRoofMakeModuleInstArea = (flatBatchType) => { + //지붕 객체 반환 + + const moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴 + const roofs = canvas.getObjects().filter((obj) => obj.name === 'roof') + let offsetLength = -90 + + if (!roofs) { + return + } + + 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: [], + }) + + setupSurface.setViewLengthText(false) + canvas.add(setupSurface) //모듈설치면 만들기 + + //남쪽 선택 + if (flatBatchType === 'excreta') { + //변별로 선택 + const excretaLines = canvas.getObjects().filter((obj) => obj.name === 'flatExcretaLine') + excretaLines.forEach((obj) => { + if (obj.isSelected === true) { + const points1 = { x: obj.x1, y: obj.y1 } + const points2 = { x: obj.x2, y: obj.y2 } + const angle = calculateAngle(points1, points2) + + roof.angle = -angle + setupSurface.angle = -angle + roof.fire('modified') + setupSurface.fire('modified') + } + canvas.remove(obj) + }) + } else { + roof.angle = -compasDeg + setupSurface.angle = -compasDeg + } + canvas.renderAll() + + let currentPoints = setupSurface.getCurrentPoints() + let lines = [] + + for (let i = 0; i < currentPoints.length; i++) { + const start = currentPoints[i] + const end = currentPoints[(i + 1) % currentPoints.length] + const line = new QLine([start.x, start.y, end.x, end.y], {}) + lines.push(line) + } + + setupSurface.lines.forEach((targetLine, index) => { + targetLine.x1 = lines[index].x1 + targetLine.y1 = lines[index].line.y1 + targetLine.x2 = lines[index].line.x2 + targetLine.y2 = lines[index].line.y2 + }) + + const flowLines = { + bottom: bottomTopFlowLine(setupSurface).find((obj) => obj.target === 'bottom'), + top: bottomTopFlowLine(setupSurface).find((obj) => obj.target === 'top'), + left: leftRightFlowLine(setupSurface).find((obj) => obj.target === 'left'), + right: leftRightFlowLine(setupSurface).find((obj) => obj.target === 'right'), + } + + setupSurface.set({ flowLines: flowLines }) //지붕면 선택 금지 roof.set({ @@ -1306,13 +1415,13 @@ export function useModuleBasicSetting() { const pointX2 = coords[2].x + ((coords[2].y - top) / (coords[2].y - coords[1].y)) * (coords[1].x - coords[2].x) const pointY2 = top - // const finalLine = new QLine([pointX1, pointY1, pointX2, pointY2], { - // stroke: 'red', - // strokeWidth: 1, - // selectable: true, - // }) - // canvas?.add(finalLine) - // canvas?.renderAll() + const finalLine = new QLine([pointX1, pointY1, pointX2, pointY2], { + stroke: 'red', + strokeWidth: 1, + selectable: true, + }) + canvas?.add(finalLine) + canvas?.renderAll() let rtnObj //평평하면 @@ -1429,13 +1538,13 @@ export function useModuleBasicSetting() { const pointX2 = top const pointY2 = coords[2].y + ((coords[2].x - top) / (coords[2].x - coords[1].x)) * (coords[1].y - coords[2].y) - // const finalLine = new QLine([pointX1, pointY1, pointX2, pointY2], { - // stroke: 'red', - // strokeWidth: 1, - // selectable: true, - // }) - // canvas?.add(finalLine) - // canvas?.renderAll() + const finalLine = new QLine([pointX1, pointY1, pointX2, pointY2], { + stroke: 'red', + strokeWidth: 1, + selectable: true, + }) + canvas?.add(finalLine) + canvas?.renderAll() let rtnObj //평평하면 @@ -1526,27 +1635,8 @@ export function useModuleBasicSetting() { } const manualFlatroofModuleSetup = (placementFlatRef) => { - const moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴 - let applyAngle + let moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴 let flatBatchType = placementFlatRef.setupLocation.current.value - let excretaLinesAngle = [] - - if (flatBatchType === 'excreta') { - const excretaLines = canvas.getObjects().filter((obj) => obj.name === 'flatExcretaLine') - excretaLines.forEach((obj) => { - if (obj.isSelected) { - const points1 = { x: obj.x1, y: obj.y1 } - const points2 = { x: obj.x2, y: obj.y2 } - excretaLinesAngle.push({ - surfaceId: obj.surfaceId, - angle: calculateAngle(points1, points2), - }) - } - canvas.remove(obj) - }) - } - - //calculateAngle const batchObjects = canvas ?.getObjects() @@ -1573,29 +1663,29 @@ export function useModuleBasicSetting() { name: 'module', } - function getRotatedCorners(rect) { - // 사각형의 중심점 - const center = rect.getCenterPoint() + // function getRotatedCorners(rect) { + // // 사각형의 중심점 + // const center = rect.getCenterPoint() - // 사각형의 원래 꼭짓점 좌표 (로컬 좌표 기준) - const halfWidth = (rect.width / 2) * rect.scaleX - const halfHeight = (rect.height / 2) * rect.scaleY + // // 사각형의 원래 꼭짓점 좌표 (로컬 좌표 기준) + // const halfWidth = (rect.width / 2) * rect.scaleX + // const halfHeight = (rect.height / 2) * rect.scaleY - const corners = [ - { x: -halfWidth, y: -halfHeight }, // 좌상단 - { x: halfWidth, y: -halfHeight }, // 우상단 - { x: halfWidth, y: halfHeight }, // 우하단 - { x: -halfWidth, y: halfHeight }, // 좌하단 - ] + // const corners = [ + // { x: -halfWidth, y: -halfHeight }, // 좌상단 + // { x: halfWidth, y: -halfHeight }, // 우상단 + // { x: halfWidth, y: halfHeight }, // 우하단 + // { x: -halfWidth, y: halfHeight }, // 좌하단 + // ] - // 각 꼭짓점 좌표를 캔버스 좌표로 변환 - const transformedCorners = corners.map((corner) => { - const point = new fabric.Point(corner.x, corner.y) - return fabric.util.transformPoint(point, rect.calcTransformMatrix()) - }) + // // 각 꼭짓점 좌표를 캔버스 좌표로 변환 + // const transformedCorners = corners.map((corner) => { + // const point = new fabric.Point(corner.x, corner.y) + // return fabric.util.transformPoint(point, rect.calcTransformMatrix()) + // }) - return transformedCorners - } + // return transformedCorners + // } if (moduleSetupSurfaces.length !== 0) { let tempModule @@ -1613,35 +1703,19 @@ export function useModuleBasicSetting() { turfPolygon = polygonToTurfPolygon(moduleSetupSurfaces[i], true) trestlePolygon = moduleSetupSurfaces[i] manualDrawModules = moduleSetupSurfaces[i].modules // 앞에서 자동으로 했을때 추가됨 + flowDirection = moduleSetupSurfaces[i].flowDirection //도형의 방향 - - if (flatBatchType === 'excreta') { - const tempLine = excretaLinesAngle.find((obj) => obj.surfaceId === trestlePolygon.surfaceId) - if (tempLine) { - applyAngle = tempLine.angle - } else { - //혹시나 두개의 지붕을 그리고 한쪽면만 선택했을때 한면은 그냥 기본 기울기를 준다 - applyAngle = compasDeg - } - } - let width = flowDirection === 'south' || flowDirection === 'north' ? 172 : 113 let height = flowDirection === 'south' || flowDirection === 'north' ? 113 : 172 - const angledModule = new fabric.Rect({ - width: width, - height: height, - left: mousePoint.x - width / 2, - top: mousePoint.y - height / 2, - }) + const points = [ + { x: mousePoint.x - width / 2, y: mousePoint.y - height / 2 }, + { x: mousePoint.x + width / 2, y: mousePoint.y - height / 2 }, + { x: mousePoint.x + width / 2, y: mousePoint.y + height / 2 }, + { x: mousePoint.x - width / 2, y: mousePoint.y + height / 2 }, + ] - const center = angledModule.getCenterPoint() - angledModule.set('angle', applyAngle) - angledModule.setPositionByOrigin(center, 'center', 'center') - - const points = getRotatedCorners(angledModule) // const turfPoints = coordToTurfPolygon(points) - if (turf.booleanWithin(turfPoints, turfPolygon)) { let isDrawing = false @@ -1651,139 +1725,153 @@ export function useModuleBasicSetting() { tempModule = new QPolygon(points, { fill: 'white', stroke: 'black', - strokeWidth: 0.3, + strokeWidth: 1, + width: width, + height: height, + left: mousePoint.x - width / 2, + top: mousePoint.y - height / 2, + selectable: false, + lockMovementX: true, + lockMovementY: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, + opacity: 0.8, name: 'tempModule', + parentId: moduleSetupSurfaces[i].parentId, }) canvas?.add(tempModule) //움직여가면서 추가됨 - canvas?.renderAll() /** * 스냅기능 */ - let snapDistance = 10 - let cellSnapDistance = 20 + // let snapDistance = 10 + // let cellSnapDistance = 20 - // if (applyAngle === 90 || applyAngle === 180 || applyAngle === 270 || applyAngle === 0) { - // const trestleLeft = moduleSetupSurfaces[i].left - // const trestleTop = moduleSetupSurfaces[i].top - // const trestleRight = trestleLeft + moduleSetupSurfaces[i].width * moduleSetupSurfaces[i].scaleX - // const trestleBottom = trestleTop + moduleSetupSurfaces[i].height * moduleSetupSurfaces[i].scaleY - // const bigCenterY = (trestleTop + trestleTop + moduleSetupSurfaces[i].height) / 2 + // const trestleLeft = moduleSetupSurfaces[i].left + // const trestleTop = moduleSetupSurfaces[i].top + // const trestleRight = trestleLeft + moduleSetupSurfaces[i].width * moduleSetupSurfaces[i].scaleX + // const trestleBottom = trestleTop + moduleSetupSurfaces[i].height * moduleSetupSurfaces[i].scaleY + // const bigCenterY = (trestleTop + trestleTop + moduleSetupSurfaces[i].height) / 2 - // // 작은 폴리곤의 경계 좌표 계산 - // const smallLeft = tempModule.left - // const smallTop = tempModule.top - // const smallRight = smallLeft + tempModule.width * tempModule.scaleX - // const smallBottom = smallTop + tempModule.height * tempModule.scaleY - // const smallCenterX = smallLeft + (tempModule.width * tempModule.scaleX) / 2 - // const smallCenterY = smallTop + (tempModule.height * tempModule.scaleX) / 2 + // // 작은 폴리곤의 경계 좌표 계산 + // const smallLeft = tempModule.left + // const smallTop = tempModule.top + // const smallRight = smallLeft + tempModule.width * tempModule.scaleX + // const smallBottom = smallTop + tempModule.height * tempModule.scaleY + // const smallCenterX = smallLeft + (tempModule.width * tempModule.scaleX) / 2 + // const smallCenterY = smallTop + (tempModule.height * tempModule.scaleX) / 2 - // if (manualDrawModules) { - // manualDrawModules.forEach((cell) => { - // const holdCellLeft = cell.left - // const holdCellTop = cell.top - // const holdCellRight = holdCellLeft + cell.width * cell.scaleX - // const holdCellBottom = holdCellTop + cell.height * cell.scaleY - // const holdCellCenterX = holdCellLeft + (cell.width * cell.scaleX) / 2 - // const holdCellCenterY = holdCellTop + (cell.height * cell.scaleY) / 2 + // /** + // * 미리 깔아놓은 셀이 있을때 셀에 흡착됨 + // */ + // if (manualDrawModules) { + // manualDrawModules.forEach((cell) => { + // const holdCellLeft = cell.left + // const holdCellTop = cell.top + // const holdCellRight = holdCellLeft + cell.width * cell.scaleX + // const holdCellBottom = holdCellTop + cell.height * cell.scaleY + // const holdCellCenterX = holdCellLeft + (cell.width * cell.scaleX) / 2 + // const holdCellCenterY = holdCellTop + (cell.height * cell.scaleY) / 2 - // //설치된 셀에 좌측에 스냅 - // if (Math.abs(smallRight - holdCellLeft) < snapDistance) { - // tempModule.left = holdCellLeft - width - 0.5 - // } + // //설치된 셀에 좌측에 스냅 + // if (Math.abs(smallRight - holdCellLeft) < snapDistance) { + // tempModule.left = holdCellLeft - width - 0.5 + // } - // //설치된 셀에 우측에 스냅 - // if (Math.abs(smallLeft - holdCellRight) < snapDistance) { - // tempModule.left = holdCellRight + 0.5 - // } + // //설치된 셀에 우측에 스냅 + // if (Math.abs(smallLeft - holdCellRight) < snapDistance) { + // tempModule.left = holdCellRight + 0.5 + // } - // //설치된 셀에 위쪽에 스냅 - // if (Math.abs(smallBottom - holdCellTop) < snapDistance) { - // tempModule.top = holdCellTop - height - 0.5 - // } + // //설치된 셀에 위쪽에 스냅 + // if (Math.abs(smallBottom - holdCellTop) < snapDistance) { + // tempModule.top = holdCellTop - height - 0.5 + // } - // //설치된 셀에 밑쪽에 스냅 - // if (Math.abs(smallTop - holdCellBottom) < snapDistance) { - // tempModule.top = holdCellBottom + 0.5 - // } - // //가운데 -> 가운데 - // if (Math.abs(smallCenterX - holdCellCenterX) < cellSnapDistance) { - // tempModule.left = holdCellCenterX - width / 2 - // } - // //왼쪽 -> 가운데 - // if (Math.abs(smallLeft - holdCellCenterX) < cellSnapDistance) { - // tempModule.left = holdCellCenterX - // } - // // 오른쪽 -> 가운데 - // if (Math.abs(smallRight - holdCellCenterX) < cellSnapDistance) { - // tempModule.left = holdCellCenterX - width - // } - // //세로 가운데 -> 가운데 - // if (Math.abs(smallCenterY - holdCellCenterY) < cellSnapDistance) { - // tempModule.top = holdCellCenterY - height / 2 - // } - // //위쪽 -> 가운데 - // if (Math.abs(smallTop - holdCellCenterY) < cellSnapDistance) { - // tempModule.top = holdCellCenterY - // } - // //아랫쪽 -> 가운데 - // if (Math.abs(smallBottom - holdCellCenterY) < cellSnapDistance) { - // tempModule.top = holdCellCenterY - height - // } - // }) + // //설치된 셀에 밑쪽에 스냅 + // if (Math.abs(smallTop - holdCellBottom) < snapDistance) { + // tempModule.top = holdCellBottom + 0.5 + // } + // //가운데 -> 가운데 + // if (Math.abs(smallCenterX - holdCellCenterX) < cellSnapDistance) { + // tempModule.left = holdCellCenterX - width / 2 + // } + // //왼쪽 -> 가운데 + // if (Math.abs(smallLeft - holdCellCenterX) < cellSnapDistance) { + // tempModule.left = holdCellCenterX + // } + // // 오른쪽 -> 가운데 + // if (Math.abs(smallRight - holdCellCenterX) < cellSnapDistance) { + // tempModule.left = holdCellCenterX - width + // } + // //세로 가운데 -> 가운데 + // if (Math.abs(smallCenterY - holdCellCenterY) < cellSnapDistance) { + // tempModule.top = holdCellCenterY - height / 2 + // } + // //위쪽 -> 가운데 + // if (Math.abs(smallTop - holdCellCenterY) < cellSnapDistance) { + // tempModule.top = holdCellCenterY + // } + // //아랫쪽 -> 가운데 + // if (Math.abs(smallBottom - holdCellCenterY) < cellSnapDistance) { + // tempModule.top = holdCellCenterY - height + // } + // }) + // } + + // // 위쪽 변에 스냅 + // if (Math.abs(smallTop - trestleTop) < snapDistance) { + // tempModule.top = trestleTop + // } + + // // 아래쪽 변에 스냅 + // if (Math.abs(smallTop + tempModule.height * tempModule.scaleY - (trestleTop + moduleSetupSurfaces[i].height)) < snapDistance) { + // tempModule.top = trestleTop + moduleSetupSurfaces[i].height - tempModule.height * tempModule.scaleY + // } + + // // 왼쪽변에 스냅 + // if (Math.abs(smallLeft - trestleLeft) < snapDistance) { + // tempModule.left = trestleLeft + // } + // //오른쪽 변에 스냅 + // if (Math.abs(smallRight - trestleRight) < snapDistance) { + // tempModule.left = trestleRight - tempModule.width * tempModule.scaleX + // } + + // if (flowDirection === 'south' || flowDirection === 'north') { + // // 모듈왼쪽이 세로중앙선에 붙게 스냅 + // if (Math.abs(smallLeft - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) { + // tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 // } - // // 위쪽 변에 스냅 - // if (Math.abs(smallTop - trestleTop) < snapDistance) { - // tempModule.top = trestleTop + // // 모듈이 가운데가 세로중앙선에 붙게 스냅 + // if (Math.abs(smallCenterX - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) { + // tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - (tempModule.width * tempModule.scaleX) / 2 // } - // // 아래쪽 변에 스냅 - // if (Math.abs(smallTop + tempModule.height * tempModule.scaleY - (trestleTop + moduleSetupSurfaces[i].height)) < snapDistance) { - // tempModule.top = trestleTop + moduleSetupSurfaces[i].height - tempModule.height * tempModule.scaleY + // // 모듈오른쪽이 세로중앙선에 붙게 스냅 + // if (Math.abs(smallRight - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) { + // tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - tempModule.width * tempModule.scaleX + // } + // } else { + // // 모듈이 가로중앙선에 스냅 + // if (Math.abs(smallTop + tempModule.height / 2 - bigCenterY) < snapDistance) { + // tempModule.top = bigCenterY - tempModule.height / 2 // } - // // 왼쪽변에 스냅 - // if (Math.abs(smallLeft - trestleLeft) < snapDistance) { - // tempModule.left = trestleLeft + // if (Math.abs(smallTop - (trestleTop + moduleSetupSurfaces[i].height / 2)) < snapDistance) { + // tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2 // } - // //오른쪽 변에 스냅 - // if (Math.abs(smallRight - trestleRight) < snapDistance) { - // tempModule.left = trestleRight - tempModule.width * tempModule.scaleX - // } - - // if (flowDirection === 'south' || flowDirection === 'north') { - // // 모듈왼쪽이 세로중앙선에 붙게 스냅 - // if (Math.abs(smallLeft - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) { - // tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - // } - - // // 모듈이 가운데가 세로중앙선에 붙게 스냅 - // if (Math.abs(smallCenterX - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) { - // tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - (tempModule.width * tempModule.scaleX) / 2 - // } - - // // 모듈오른쪽이 세로중앙선에 붙게 스냅 - // if (Math.abs(smallRight - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) { - // tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - tempModule.width * tempModule.scaleX - // } - // } else { - // // 모듈이 가로중앙선에 스냅 - // if (Math.abs(smallTop + tempModule.height / 2 - bigCenterY) < snapDistance) { - // tempModule.top = bigCenterY - tempModule.height / 2 - // } - - // if (Math.abs(smallTop - (trestleTop + moduleSetupSurfaces[i].height / 2)) < snapDistance) { - // tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2 - // } - // // 모듈 밑면이 가로중앙선에 스냅 - // if (Math.abs(smallBottom - (trestleTop + moduleSetupSurfaces[i].height / 2)) < snapDistance) { - // tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2 - tempModule.height * tempModule.scaleY - // } + // // 모듈 밑면이 가로중앙선에 스냅 + // if (Math.abs(smallBottom - (trestleTop + moduleSetupSurfaces[i].height / 2)) < snapDistance) { + // tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2 - tempModule.height * tempModule.scaleY // } // } + tempModule.setCoords() + canvas?.renderAll() inside = true break } else { @@ -1849,9 +1937,7 @@ export function useModuleBasicSetting() { const autoFlatroofModuleSetup = (placementFlatRef) => { initEvent() //마우스 이벤트 초기화 - let flatBatchType = placementFlatRef.setupLocation.current.value const moduleSetupSurfaces = moduleSetupSurface //선택 설치면 - const notSelectedTrestlePolygons = canvas ?.getObjects() .filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && !moduleSetupSurfaces.includes(obj)) //설치면이 아닌것 @@ -1887,6 +1973,38 @@ export function useModuleBasicSetting() { } }) + const flatBatchType = placementFlatRef.setupLocation.current.value + + //남쪽 선택 + // if (flatBatchType === 'excreta') { + // //변별로 선택 + // const excretaLines = canvas.getObjects().filter((obj) => obj.name === 'flatExcretaLine') + // excretaLines.forEach((obj) => { + // if (obj.isSelected === true) { + // const points1 = { x: obj.x1, y: obj.y1 } + // const points2 = { x: obj.x2, y: obj.y2 } + // const angle = calculateAngle(points1, points2) + + // const targetdSurface = moduleSetupSurfaces.filter((surface) => surface.surfaceId === obj.surfaceId)[0] + // const targetRoof = canvas.getObjects().filter((roof) => roof.name === POLYGON_TYPE.ROOF && roof.id === targetdSurface.parentId)[0] + + // targetRoof.angle = -angle + // targetdSurface.angle = -angle + + // targetRoof.fire('modified') + // targetdSurface.fire('modified') + // } + // canvas.remove(obj) + // }) + // } else { + // moduleSetupSurfaces.forEach((surface) => { + // const targetRoof = canvas.getObjects().filter((roof) => roof.name === POLYGON_TYPE.ROOF && roof.id === surface.parentId)[0] + // if (targetRoof) targetRoof.angle = -compasDeg + // surface.angle = -compasDeg + // }) + // } + // canvas.renderAll() + const moduleOptions = { fill: '#BFFD9F', stroke: 'black', @@ -1902,7 +2020,7 @@ export function useModuleBasicSetting() { name: 'module', } - let leftMargin, bottomMargin, square, chidoriLength + let leftMargin, bottomMargin, square //선택된 지붕안에 오브젝트(도머, 개구등)이 있는지 확인하는 로직 포함되면 배열 반환 const objectsIncludeSurface = (turfModuleSetupSurface) => { @@ -2151,8 +2269,8 @@ export function useModuleBasicSetting() { } const surfaceMaxLines = findSetupSurfaceMaxLines(moduleSetupSurface) - const marginWidth = 0 - const marginHeight = 0 + const marginWidth = 1 + const marginHeight = 1 canvas.renderAll() @@ -2181,21 +2299,21 @@ export function useModuleBasicSetting() { canvas?.renderAll() - //나간애들 제외하고 설치된 애들로 겹친애들 삭제 하기 - // setupedModules.forEach((module, index) => { - // if (isMaxSetup && index > 0) { - // const isOverlap = turf.booleanOverlap(polygonToTurfPolygon(setupedModules[index - 1]), polygonToTurfPolygon(module)) - // //겹치는지 확인 - // if (isOverlap) { - // //겹쳐있으면 삭제 - // // canvas?.remove(module) - // module.set({ fill: 'rgba(72, 161, 250, 0.4)', stroke: 'black', strokeWidth: 0.1 }) - // canvas.renderAll() - // setupedModules.splice(index, 1) - // return false - // } - // } - // }) + // 나간애들 제외하고 설치된 애들로 겹친애들 삭제 하기 + setupedModules.forEach((module, index) => { + if (index > 0) { + const isOverlap = turf.booleanOverlap(polygonToTurfPolygon(setupedModules[index - 1]), polygonToTurfPolygon(module)) + //겹치는지 확인 + if (isOverlap) { + //겹쳐있으면 삭제 + // canvas?.remove(module) + module.set({ fill: 'rgba(72, 161, 250, 0.4)', stroke: 'black', strokeWidth: 0.1 }) + canvas.renderAll() + setupedModules.splice(index, 1) + return false + } + } + }) moduleSetupSurface.set({ modules: setupedModules }) @@ -2209,49 +2327,6 @@ export function useModuleBasicSetting() { // console.log(calculateForApi()) } - const flatRoofMakeSurface = (roof, setupSurface) => { - setupSurface.angle = -compasDeg - roof.angle = -compasDeg - - const roofPoints = roof.getCurrentPoints() - const roofLines = roofPoints.map((point, index) => { - const nextIndex = (index + 1) % roofPoints.length - const nextPoint = roofPoints[nextIndex] - - return { - x1: point.x, - y1: point.y, - x2: nextPoint.x, - y2: nextPoint.y, - } - }) - roof.set({ lines: roofLines }) - roof.fire('modified') - - const surfacePoints = setupSurface.getCurrentPoints() - const surfaceLines = surfacePoints.map((point, index) => { - const nextIndex = (index + 1) % surfacePoints.length - const nextPoint = surfacePoints[nextIndex] - - return { - x1: point.x, - y1: point.y, - x2: nextPoint.x, - y2: nextPoint.y, - } - }) - setupSurface.set({ lines: surfaceLines }) - - const flowLines = { - bottom: bottomTopFlowLine(setupSurface).find((obj) => obj.target === 'bottom'), - top: bottomTopFlowLine(setupSurface).find((obj) => obj.target === 'top'), - left: leftRightFlowLine(setupSurface).find((obj) => obj.target === 'left'), - right: leftRightFlowLine(setupSurface).find((obj) => obj.target === 'right'), - } - setupSurface.set({ flowLines: flowLines }) - setupSurface.fire('modified') - } - return { makeModuleInstArea, manualModuleSetup, @@ -2259,5 +2334,6 @@ export function useModuleBasicSetting() { restoreModuleInstArea, manualFlatroofModuleSetup, autoFlatroofModuleSetup, + flatRoofMakeModuleInstArea, } } From 0cee2ec00defcc12be16383eafb9fd751716c541 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Fri, 13 Dec 2024 15:57:36 +0900 Subject: [PATCH 005/114] =?UTF-8?q?=EB=AA=A8=EB=93=88=20=ED=9A=8C=EB=A1=9C?= =?UTF-8?q?,=20=EC=9C=A1=EC=A7=80=EB=B6=95=20=ED=9A=8C=EC=A0=84=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80=20=EC=9E=91=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modal/basic/step/pitch/PitchPlacement.jsx | 8 +- src/hooks/module/useModuleBasicSetting.js | 481 ++++++++---------- 2 files changed, 221 insertions(+), 268 deletions(-) diff --git a/src/components/floor-plan/modal/basic/step/pitch/PitchPlacement.jsx b/src/components/floor-plan/modal/basic/step/pitch/PitchPlacement.jsx index 51274ea3..a292ed2d 100644 --- a/src/components/floor-plan/modal/basic/step/pitch/PitchPlacement.jsx +++ b/src/components/floor-plan/modal/basic/step/pitch/PitchPlacement.jsx @@ -9,17 +9,16 @@ import { useEvent } from '@/hooks/useEvent' const PitchPlacement = forwardRef((props, refs) => { const { getMessage } = useMessage() const [setupLocation, setSetupLocation] = useState('south') - const { flatRoofMakeModuleInstArea } = useModuleBasicSetting() + const { makeModuleInstArea } = useModuleBasicSetting() const canvas = useRecoilValue(canvasState) const { initEvent } = useEvent() useEffect(() => { - flatRoofMakeModuleInstArea(setupLocation) + makeModuleInstArea() }, []) useEffect(() => { handleChangeSetupLocation() - flatRoofMakeModuleInstArea(setupLocation) }, [setupLocation]) const moduleData = { @@ -57,9 +56,9 @@ const PitchPlacement = forwardRef((props, refs) => { return null } else { const moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴 - moduleSetupSurfaces.forEach((surface, index) => { const excretaLine = surface.lines + excretaLine.forEach((line) => { line.set({ stroke: '#642EFB', @@ -73,7 +72,6 @@ const PitchPlacement = forwardRef((props, refs) => { excretaLine.forEach((obj) => obj.set({ stroke: '#642EFB', isSelected: false })) if (!line.isSelected) { line.set({ stroke: 'red', isSelected: true }) - surface.fire('mousedown') } else { line.set({ stroke: '#642EFB', isSelected: false }) } diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index 6d8812e7..43e7e388 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -52,7 +52,7 @@ export function useModuleBasicSetting() { const makeModuleInstArea = () => { //지붕 객체 반환 const roofs = canvas.getObjects().filter((obj) => obj.name === 'roof') - let offsetLength = -20 + let offsetLength = canvasSetting.roofSizeSet === 3 ? -90 : -20 if (!roofs) { return @@ -97,125 +97,18 @@ export function useModuleBasicSetting() { setupSurface.setViewLengthText(false) canvas.add(setupSurface) //모듈설치면 만들기 - const flowLines = { - bottom: bottomTopFlowLine(setupSurface).find((obj) => obj.target === 'bottom'), - top: bottomTopFlowLine(setupSurface).find((obj) => obj.target === 'top'), - left: leftRightFlowLine(setupSurface).find((obj) => obj.target === 'left'), - right: leftRightFlowLine(setupSurface).find((obj) => obj.target === 'right'), + //육지붕이 아닐때만 넣는다 육지붕일땐 클릭 이벤트에 별도로 넣어놓음 + if (canvasSetting.roofSizeSet !== 3) { + const flowLines = { + bottom: bottomTopFlowLine(setupSurface).find((obj) => obj.target === 'bottom'), + top: bottomTopFlowLine(setupSurface).find((obj) => obj.target === 'top'), + left: leftRightFlowLine(setupSurface).find((obj) => obj.target === 'left'), + right: leftRightFlowLine(setupSurface).find((obj) => obj.target === 'right'), + } + + setupSurface.set({ flowLines: flowLines }) } - setupSurface.set({ flowLines: flowLines }) - - //지붕면 선택 금지 - roof.set({ - selectable: false, - }) - - //모듈설치면 클릭이벤트 - addTargetMouseEventListener('mousedown', setupSurface, function () { - toggleSelection(setupSurface) - }) - }) - } - - const flatRoofMakeModuleInstArea = (flatBatchType) => { - //지붕 객체 반환 - - const moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴 - const roofs = canvas.getObjects().filter((obj) => obj.name === 'roof') - let offsetLength = -90 - - if (!roofs) { - return - } - - 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: [], - }) - - setupSurface.setViewLengthText(false) - canvas.add(setupSurface) //모듈설치면 만들기 - - //남쪽 선택 - if (flatBatchType === 'excreta') { - //변별로 선택 - const excretaLines = canvas.getObjects().filter((obj) => obj.name === 'flatExcretaLine') - excretaLines.forEach((obj) => { - if (obj.isSelected === true) { - const points1 = { x: obj.x1, y: obj.y1 } - const points2 = { x: obj.x2, y: obj.y2 } - const angle = calculateAngle(points1, points2) - - roof.angle = -angle - setupSurface.angle = -angle - roof.fire('modified') - setupSurface.fire('modified') - } - canvas.remove(obj) - }) - } else { - roof.angle = -compasDeg - setupSurface.angle = -compasDeg - } - canvas.renderAll() - - let currentPoints = setupSurface.getCurrentPoints() - let lines = [] - - for (let i = 0; i < currentPoints.length; i++) { - const start = currentPoints[i] - const end = currentPoints[(i + 1) % currentPoints.length] - const line = new QLine([start.x, start.y, end.x, end.y], {}) - lines.push(line) - } - - setupSurface.lines.forEach((targetLine, index) => { - targetLine.x1 = lines[index].x1 - targetLine.y1 = lines[index].line.y1 - targetLine.x2 = lines[index].line.x2 - targetLine.y2 = lines[index].line.y2 - }) - - const flowLines = { - bottom: bottomTopFlowLine(setupSurface).find((obj) => obj.target === 'bottom'), - top: bottomTopFlowLine(setupSurface).find((obj) => obj.target === 'top'), - left: leftRightFlowLine(setupSurface).find((obj) => obj.target === 'left'), - right: leftRightFlowLine(setupSurface).find((obj) => obj.target === 'right'), - } - - setupSurface.set({ flowLines: flowLines }) - //지붕면 선택 금지 roof.set({ selectable: false, @@ -1420,8 +1313,8 @@ export function useModuleBasicSetting() { strokeWidth: 1, selectable: true, }) - canvas?.add(finalLine) - canvas?.renderAll() + // canvas?.add(finalLine) + // canvas?.renderAll() let rtnObj //평평하면 @@ -1543,8 +1436,8 @@ export function useModuleBasicSetting() { strokeWidth: 1, selectable: true, }) - canvas?.add(finalLine) - canvas?.renderAll() + // canvas?.add(finalLine) + // canvas?.renderAll() let rtnObj //평평하면 @@ -1695,6 +1588,37 @@ export function useModuleBasicSetting() { let flowDirection let trestlePolygon + //남쪽 선택 + if (flatBatchType === 'excreta') { + //변별로 선택 + const excretaLines = canvas.getObjects().filter((obj) => obj.name === 'flatExcretaLine') + excretaLines.forEach((obj) => { + if (obj.isSelected === true) { + const points1 = { x: obj.x1, y: obj.y1 } + const points2 = { x: obj.x2, y: obj.y2 } + const angle = calculateAngle(points1, points2) + + //변별로 선택으로 되어있을때 모듈면을 회전시키기 + const targetdSurface = moduleSetupSurfaces.filter((surface) => surface.surfaceId === obj.surfaceId)[0] + targetdSurface.angle = -angle + //변별로 선택되어있는 지붕도 회전시키기 + const targetRoof = canvas.getObjects().filter((roof) => roof.name === POLYGON_TYPE.ROOF && roof.id === targetdSurface.parentId)[0] + targetRoof.angle = -angle + + targetRoof.fire('modified') + targetdSurface.fire('modified') + } + canvas.remove(obj) + }) + } else { + moduleSetupSurfaces.forEach((surface) => { + const targetRoof = canvas.getObjects().filter((roof) => roof.name === POLYGON_TYPE.ROOF && roof.id === surface.parentId)[0] + if (targetRoof) targetRoof.angle = -compasDeg + surface.angle = -compasDeg + }) + } + canvas.renderAll() + addCanvasMouseEventListener('mouse:move', (e) => { //마우스 이벤트 삭제 후 재추가 const mousePoint = canvas.getPointer(e.e) @@ -1746,129 +1670,129 @@ export function useModuleBasicSetting() { /** * 스냅기능 */ - // let snapDistance = 10 - // let cellSnapDistance = 20 + let snapDistance = 10 + let cellSnapDistance = 20 - // const trestleLeft = moduleSetupSurfaces[i].left - // const trestleTop = moduleSetupSurfaces[i].top - // const trestleRight = trestleLeft + moduleSetupSurfaces[i].width * moduleSetupSurfaces[i].scaleX - // const trestleBottom = trestleTop + moduleSetupSurfaces[i].height * moduleSetupSurfaces[i].scaleY - // const bigCenterY = (trestleTop + trestleTop + moduleSetupSurfaces[i].height) / 2 + const trestleLeft = moduleSetupSurfaces[i].left + const trestleTop = moduleSetupSurfaces[i].top + const trestleRight = trestleLeft + moduleSetupSurfaces[i].width * moduleSetupSurfaces[i].scaleX + const trestleBottom = trestleTop + moduleSetupSurfaces[i].height * moduleSetupSurfaces[i].scaleY + const bigCenterY = (trestleTop + trestleTop + moduleSetupSurfaces[i].height) / 2 - // // 작은 폴리곤의 경계 좌표 계산 - // const smallLeft = tempModule.left - // const smallTop = tempModule.top - // const smallRight = smallLeft + tempModule.width * tempModule.scaleX - // const smallBottom = smallTop + tempModule.height * tempModule.scaleY - // const smallCenterX = smallLeft + (tempModule.width * tempModule.scaleX) / 2 - // const smallCenterY = smallTop + (tempModule.height * tempModule.scaleX) / 2 + // 작은 폴리곤의 경계 좌표 계산 + const smallLeft = tempModule.left + const smallTop = tempModule.top + const smallRight = smallLeft + tempModule.width * tempModule.scaleX + const smallBottom = smallTop + tempModule.height * tempModule.scaleY + const smallCenterX = smallLeft + (tempModule.width * tempModule.scaleX) / 2 + const smallCenterY = smallTop + (tempModule.height * tempModule.scaleX) / 2 - // /** - // * 미리 깔아놓은 셀이 있을때 셀에 흡착됨 - // */ - // if (manualDrawModules) { - // manualDrawModules.forEach((cell) => { - // const holdCellLeft = cell.left - // const holdCellTop = cell.top - // const holdCellRight = holdCellLeft + cell.width * cell.scaleX - // const holdCellBottom = holdCellTop + cell.height * cell.scaleY - // const holdCellCenterX = holdCellLeft + (cell.width * cell.scaleX) / 2 - // const holdCellCenterY = holdCellTop + (cell.height * cell.scaleY) / 2 + /** + * 미리 깔아놓은 셀이 있을때 셀에 흡착됨 + */ + if (manualDrawModules) { + manualDrawModules.forEach((cell) => { + const holdCellLeft = cell.left + const holdCellTop = cell.top + const holdCellRight = holdCellLeft + cell.width * cell.scaleX + const holdCellBottom = holdCellTop + cell.height * cell.scaleY + const holdCellCenterX = holdCellLeft + (cell.width * cell.scaleX) / 2 + const holdCellCenterY = holdCellTop + (cell.height * cell.scaleY) / 2 - // //설치된 셀에 좌측에 스냅 - // if (Math.abs(smallRight - holdCellLeft) < snapDistance) { - // tempModule.left = holdCellLeft - width - 0.5 - // } + //설치된 셀에 좌측에 스냅 + if (Math.abs(smallRight - holdCellLeft) < snapDistance) { + tempModule.left = holdCellLeft - width - 1 + } - // //설치된 셀에 우측에 스냅 - // if (Math.abs(smallLeft - holdCellRight) < snapDistance) { - // tempModule.left = holdCellRight + 0.5 - // } + //설치된 셀에 우측에 스냅 + if (Math.abs(smallLeft - holdCellRight) < snapDistance) { + tempModule.left = holdCellRight + 0.5 + } - // //설치된 셀에 위쪽에 스냅 - // if (Math.abs(smallBottom - holdCellTop) < snapDistance) { - // tempModule.top = holdCellTop - height - 0.5 - // } + //설치된 셀에 위쪽에 스냅 + if (Math.abs(smallBottom - holdCellTop) < snapDistance) { + tempModule.top = holdCellTop - height - 1 + } - // //설치된 셀에 밑쪽에 스냅 - // if (Math.abs(smallTop - holdCellBottom) < snapDistance) { - // tempModule.top = holdCellBottom + 0.5 - // } - // //가운데 -> 가운데 - // if (Math.abs(smallCenterX - holdCellCenterX) < cellSnapDistance) { - // tempModule.left = holdCellCenterX - width / 2 - // } - // //왼쪽 -> 가운데 - // if (Math.abs(smallLeft - holdCellCenterX) < cellSnapDistance) { - // tempModule.left = holdCellCenterX - // } - // // 오른쪽 -> 가운데 - // if (Math.abs(smallRight - holdCellCenterX) < cellSnapDistance) { - // tempModule.left = holdCellCenterX - width - // } - // //세로 가운데 -> 가운데 - // if (Math.abs(smallCenterY - holdCellCenterY) < cellSnapDistance) { - // tempModule.top = holdCellCenterY - height / 2 - // } - // //위쪽 -> 가운데 - // if (Math.abs(smallTop - holdCellCenterY) < cellSnapDistance) { - // tempModule.top = holdCellCenterY - // } - // //아랫쪽 -> 가운데 - // if (Math.abs(smallBottom - holdCellCenterY) < cellSnapDistance) { - // tempModule.top = holdCellCenterY - height - // } - // }) - // } + //설치된 셀에 밑쪽에 스냅 + if (Math.abs(smallTop - holdCellBottom) < snapDistance) { + tempModule.top = holdCellBottom + 1 + } + //가운데 -> 가운데 + if (Math.abs(smallCenterX - holdCellCenterX) < cellSnapDistance) { + tempModule.left = holdCellCenterX - width / 2 + } + //왼쪽 -> 가운데 + if (Math.abs(smallLeft - holdCellCenterX) < cellSnapDistance) { + tempModule.left = holdCellCenterX + } + // 오른쪽 -> 가운데 + if (Math.abs(smallRight - holdCellCenterX) < cellSnapDistance) { + tempModule.left = holdCellCenterX - width + } + //세로 가운데 -> 가운데 + if (Math.abs(smallCenterY - holdCellCenterY) < cellSnapDistance) { + tempModule.top = holdCellCenterY - height / 2 + } + //위쪽 -> 가운데 + if (Math.abs(smallTop - holdCellCenterY) < cellSnapDistance) { + tempModule.top = holdCellCenterY + } + //아랫쪽 -> 가운데 + if (Math.abs(smallBottom - holdCellCenterY) < cellSnapDistance) { + tempModule.top = holdCellCenterY - height + } + }) + } - // // 위쪽 변에 스냅 - // if (Math.abs(smallTop - trestleTop) < snapDistance) { - // tempModule.top = trestleTop - // } + // 위쪽 변에 스냅 + if (Math.abs(smallTop - trestleTop) < snapDistance) { + tempModule.top = trestleTop + } - // // 아래쪽 변에 스냅 - // if (Math.abs(smallTop + tempModule.height * tempModule.scaleY - (trestleTop + moduleSetupSurfaces[i].height)) < snapDistance) { - // tempModule.top = trestleTop + moduleSetupSurfaces[i].height - tempModule.height * tempModule.scaleY - // } + // 아래쪽 변에 스냅 + if (Math.abs(smallTop + tempModule.height * tempModule.scaleY - (trestleTop + moduleSetupSurfaces[i].height)) < snapDistance) { + tempModule.top = trestleTop + moduleSetupSurfaces[i].height - tempModule.height * tempModule.scaleY + } - // // 왼쪽변에 스냅 - // if (Math.abs(smallLeft - trestleLeft) < snapDistance) { - // tempModule.left = trestleLeft - // } - // //오른쪽 변에 스냅 - // if (Math.abs(smallRight - trestleRight) < snapDistance) { - // tempModule.left = trestleRight - tempModule.width * tempModule.scaleX - // } + // 왼쪽변에 스냅 + if (Math.abs(smallLeft - trestleLeft) < snapDistance) { + tempModule.left = trestleLeft + } + //오른쪽 변에 스냅 + if (Math.abs(smallRight - trestleRight) < snapDistance) { + tempModule.left = trestleRight - tempModule.width * tempModule.scaleX + } - // if (flowDirection === 'south' || flowDirection === 'north') { - // // 모듈왼쪽이 세로중앙선에 붙게 스냅 - // if (Math.abs(smallLeft - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) { - // tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - // } + if (flowDirection === 'south' || flowDirection === 'north') { + // 모듈왼쪽이 세로중앙선에 붙게 스냅 + if (Math.abs(smallLeft - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) { + tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 + } - // // 모듈이 가운데가 세로중앙선에 붙게 스냅 - // if (Math.abs(smallCenterX - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) { - // tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - (tempModule.width * tempModule.scaleX) / 2 - // } + // 모듈이 가운데가 세로중앙선에 붙게 스냅 + if (Math.abs(smallCenterX - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) { + tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - (tempModule.width * tempModule.scaleX) / 2 + } - // // 모듈오른쪽이 세로중앙선에 붙게 스냅 - // if (Math.abs(smallRight - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) { - // tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - tempModule.width * tempModule.scaleX - // } - // } else { - // // 모듈이 가로중앙선에 스냅 - // if (Math.abs(smallTop + tempModule.height / 2 - bigCenterY) < snapDistance) { - // tempModule.top = bigCenterY - tempModule.height / 2 - // } + // 모듈오른쪽이 세로중앙선에 붙게 스냅 + if (Math.abs(smallRight - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) { + tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - tempModule.width * tempModule.scaleX + } + } else { + // 모듈이 가로중앙선에 스냅 + if (Math.abs(smallTop + tempModule.height / 2 - bigCenterY) < snapDistance) { + tempModule.top = bigCenterY - tempModule.height / 2 + } - // if (Math.abs(smallTop - (trestleTop + moduleSetupSurfaces[i].height / 2)) < snapDistance) { - // tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2 - // } - // // 모듈 밑면이 가로중앙선에 스냅 - // if (Math.abs(smallBottom - (trestleTop + moduleSetupSurfaces[i].height / 2)) < snapDistance) { - // tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2 - tempModule.height * tempModule.scaleY - // } - // } + if (Math.abs(smallTop - (trestleTop + moduleSetupSurfaces[i].height / 2)) < snapDistance) { + tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2 + } + // 모듈 밑면이 가로중앙선에 스냅 + if (Math.abs(smallBottom - (trestleTop + moduleSetupSurfaces[i].height / 2)) < snapDistance) { + tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2 - tempModule.height * tempModule.scaleY + } + } tempModule.setCoords() canvas?.renderAll() @@ -1952,10 +1876,10 @@ export function useModuleBasicSetting() { obj.name === BATCH_TYPE.SHADOW, ) //도머s 객체 - if (moduleSetupSurfaces.length === 0) { - alert('선택된 모듈 설치면이 없습니다.') - return - } + // if (moduleSetupSurfaces.length === 0) { + // alert('선택된 모듈 설치면이 없습니다.') + // return + // } //어짜피 자동으로 누르면 선택안된데도 다 날아간다 canvas.getObjects().forEach((obj) => { @@ -1976,34 +1900,66 @@ export function useModuleBasicSetting() { const flatBatchType = placementFlatRef.setupLocation.current.value //남쪽 선택 - // if (flatBatchType === 'excreta') { - // //변별로 선택 - // const excretaLines = canvas.getObjects().filter((obj) => obj.name === 'flatExcretaLine') - // excretaLines.forEach((obj) => { - // if (obj.isSelected === true) { - // const points1 = { x: obj.x1, y: obj.y1 } - // const points2 = { x: obj.x2, y: obj.y2 } - // const angle = calculateAngle(points1, points2) + if (flatBatchType === 'excreta') { + //변별로 선택 + const excretaLines = canvas.getObjects().filter((obj) => obj.name === 'flatExcretaLine') + excretaLines.forEach((obj) => { + if (obj.isSelected === true) { + const points1 = { x: obj.x1, y: obj.y1 } + const points2 = { x: obj.x2, y: obj.y2 } + const angle = calculateAngle(points1, points2) - // const targetdSurface = moduleSetupSurfaces.filter((surface) => surface.surfaceId === obj.surfaceId)[0] - // const targetRoof = canvas.getObjects().filter((roof) => roof.name === POLYGON_TYPE.ROOF && roof.id === targetdSurface.parentId)[0] + // const targetdSurface = moduleSetupSurfaces.filter((surface) => surface.surfaceId === obj.surfaceId)[0] + const targetSurface = canvas + .getObjects() + .filter((surface) => surface.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && surface.surfaceId === obj.surfaceId)[0] + const targetRoof = canvas.getObjects().filter((roof) => roof.name === POLYGON_TYPE.ROOF && roof.id === targetSurface.parentId)[0] - // targetRoof.angle = -angle - // targetdSurface.angle = -angle + targetRoof.angle = -angle + targetSurface.angle = -angle - // targetRoof.fire('modified') - // targetdSurface.fire('modified') - // } - // canvas.remove(obj) - // }) - // } else { - // moduleSetupSurfaces.forEach((surface) => { - // const targetRoof = canvas.getObjects().filter((roof) => roof.name === POLYGON_TYPE.ROOF && roof.id === surface.parentId)[0] - // if (targetRoof) targetRoof.angle = -compasDeg - // surface.angle = -compasDeg - // }) - // } - // canvas.renderAll() + targetRoof.fire('modified') + targetSurface.fire('modified') + moduleSetupSurfaces.push(targetSurface) + } + canvas.remove(obj) + }) + } else { + moduleSetupSurfaces.forEach((surface) => { + const targetRoof = canvas.getObjects().filter((roof) => roof.name === POLYGON_TYPE.ROOF && roof.id === surface.parentId)[0] + if (targetRoof) targetRoof.angle = -compasDeg + surface.angle = -compasDeg + }) + } + canvas.renderAll() + + moduleSetupSurfaces.forEach((surface) => { + let currentPoints = surface.getCurrentPoints() + let lines = [] + + for (let i = 0; i < currentPoints.length; i++) { + const start = currentPoints[i] + const end = currentPoints[(i + 1) % currentPoints.length] + const line = new QLine([start.x, start.y, end.x, end.y], {}) + lines.push(line) + } + + surface.lines.forEach((targetLine, index) => { + targetLine.x1 = lines[index].x1 + targetLine.y1 = lines[index].y1 + targetLine.x2 = lines[index].x2 + targetLine.y2 = lines[index].y2 + }) + + const flowLines = { + bottom: bottomTopFlowLine(surface).find((obj) => obj.target === 'bottom'), + top: bottomTopFlowLine(surface).find((obj) => obj.target === 'top'), + left: leftRightFlowLine(surface).find((obj) => obj.target === 'left'), + right: leftRightFlowLine(surface).find((obj) => obj.target === 'right'), + } + + surface.set({ flowLines: flowLines }) + }) const moduleOptions = { fill: '#BFFD9F', @@ -2306,8 +2262,8 @@ export function useModuleBasicSetting() { //겹치는지 확인 if (isOverlap) { //겹쳐있으면 삭제 - // canvas?.remove(module) - module.set({ fill: 'rgba(72, 161, 250, 0.4)', stroke: 'black', strokeWidth: 0.1 }) + canvas?.remove(module) + // module.set({ fill: 'rgba(72, 161, 250, 0.4)', stroke: 'black', strokeWidth: 0.1 }) canvas.renderAll() setupedModules.splice(index, 1) return false @@ -2334,6 +2290,5 @@ export function useModuleBasicSetting() { restoreModuleInstArea, manualFlatroofModuleSetup, autoFlatroofModuleSetup, - flatRoofMakeModuleInstArea, } } From f83636af172cc708b0fbc196bb0d4bf6fb3f270a Mon Sep 17 00:00:00 2001 From: changkyu choi Date: Fri, 13 Dec 2024 17:42:09 +0900 Subject: [PATCH 006/114] =?UTF-8?q?=EB=B0=B0=EC=B9=98=20api=20=ED=8C=8C?= =?UTF-8?q?=EB=9D=BC=EB=AF=B8=ED=84=B0=20=ED=8C=A8=ED=84=B4=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Playground.jsx | 86 ++++++++++++++----------- src/hooks/common/useMasterController.js | 53 +++------------ src/models/apiModels.js | 42 ++++++++++++ 3 files changed, 100 insertions(+), 81 deletions(-) create mode 100644 src/models/apiModels.js diff --git a/src/components/Playground.jsx b/src/components/Playground.jsx index 6646aac6..ec177cd1 100644 --- a/src/components/Playground.jsx +++ b/src/components/Playground.jsx @@ -23,6 +23,8 @@ import QInput from './common/input/Qinput' import QSelect from './common/select/QSelect' import QPagination from './common/pagination/QPagination' +import { trestleRequestModels, constructionRequestModels, trestleDetailRequestModels } from '@/models/apiModels' + export default function Playground() { const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState) const [cadFileName, setCadFileName] = useRecoilState(cadFileNameState) @@ -48,8 +50,51 @@ export default function Playground() { const [users, setUsers] = useState([]) + const [trestleRequestData, setTrestleRequestData] = useState(trestleRequestModels) + const [constructionRequestData, setConstructionRequestData] = useState(constructionRequestModels) + const [trestleDetailRequestData, setTrestleDetailRequestData] = useState(trestleDetailRequestModels) + useEffect(() => { console.log('textInput:', textInput) + setTrestleRequestData({ + moduleTpCd: 'testData_1', + roofMatlCd: '', + raftBaseCd: 'testData_2', + trestleMkrCd: 'testData_3', + constMthdCd: '', + roofBaseCd: 'testData_4', + }) + + setConstructionRequestData({ + moduleTpCd: 'testData_1', + roofMatlCd: 'testData_2', + trestleMkrCd: 'testData_3', + constMthdCd: 'testData_4', + roofBaseCd: 'testData_5', + illuminationTp: 'testData_6', + instHt: 'testData_7', + stdWindSpeed: 'testData_8', + stdSnowLd: 'testData_9', + inclCd: 'testData_10', + raftBaseCd: 'testData_11', + roofPitch: 30, + }) + + setTrestleDetailRequestData({ + moduleTpCd: 'testData_1', + roofMatlCd: 'testData_2', + trestleMkrCd: 'testData_3', + constMthdCd: 'testData_4', + roofBaseCd: 'testData_5', + illuminationTp: 'testData_6', + instHt: 'testData_7', + stdWindSpeed: 'testData_8', + stdSnowLd: 'testData_9', + inclCd: 'testData_10', + constTp: 'testData_11', + mixMatlNo: 10, + roofPitch: 20, + }) }, [textInput]) useEffect(() => { console.log('numberInput:', numberInput) @@ -154,41 +199,6 @@ export default function Playground() { console.log('users:', users) }, [users]) - const trestleData = [{ moduleTpCd: '1', roofMatlCd: '2', raftBaseCd: '', trestleMkrCd: '4', constMthdCd: '', roofBaseCd: '6' }] - const constructionData = [ - { - moduleTpCd: '', - roofMatlCd: '', - trestleMkrCd: '', - constMthdCd: '', - roofBaseCd: '', - illuminationTp: '', - instHt: '', - stdWindSpeed: '', - stdSnowLd: '', - inclCd: '', - raftBaseCd: '', - roofPitch: 0, - }, - ] - const trestleDetailData = [ - { - moduleTpCd: '', - roofMatlCd: '', - trestleMkrCd: '', - constMthdCd: '', - roofBaseCd: '', - illuminationTp: '', - instHt: '', - stdWindSpeed: '', - stdSnowLd: '', - inclCd: '', - constTp: '', - mixMatlNo: 0, - roofPitch: 0, - }, - ] - return ( <>
@@ -213,7 +223,7 @@ export default function Playground() {
-
- -
+ {addedRoofs.length > 0 && ( +
+ { roof.selected)} options={addedRoofs} onChange={changeSelectedRoofMaterial} />} +
+ )}
{['R', 'C'].includes(currentRoofMaterial.widAuth) && ( - <> -
- W -
- +
+
+ W +
+
- +
)} {['R', 'C'].includes(currentRoofMaterial.lenAuth) && (
- L -
- +
+ L +
+ +
)} @@ -201,33 +227,30 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
{getMessage('modal.placement.initial.setting.rafter')}
- + {raftCodes.map((raft, index) => { + return ( + + ) + })}
)} {['C', 'R'].includes(currentRoofMaterial.roofPchAuth) && (
- {getMessage('hajebichi')} -
- +
+ {getMessage('hajebichi')} +
+ +
)} @@ -238,7 +261,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
-
diff --git a/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx b/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx index f6f1e6f1..1477a89b 100644 --- a/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx +++ b/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx @@ -3,16 +3,27 @@ import WithDraggable from '@/components/common/draggable/WithDraggable' import QSelectBox from '@/components/common/select/QSelectBox' import { useRoofAllocationSetting } from '@/hooks/roofcover/useRoofAllocationSetting' import { usePopup } from '@/hooks/usePopup' -import { useRecoilValue } from 'recoil' +import { useRecoilState, useRecoilValue } from 'recoil' import { contextPopupPositionState } from '@/store/popupAtom' +import { useEffect, useState } from 'react' +import { basicSettingState } from '@/store/settingAtom' +import { ROOF_MATERIAL_LAYOUT } from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting' export default function RoofAllocationSetting(props) { const contextPopupPosition = useRecoilValue(contextPopupPositionState) const { id, pos = contextPopupPosition } = props const { getMessage } = useMessage() const { closePopup } = usePopup() - const { handleSave, onAddRoofMaterial, onDeleteRoofMaterial, values, roofMaterials, selectedRoofMaterial, setSelectedRoofMaterial } = - useRoofAllocationSetting(id) + const { + handleSave, + onAddRoofMaterial, + onDeleteRoofMaterial, + roofMaterials, + setCurrentRoofMaterial, + roofList, + handleDefaultRoofMaterial, + handleChangeRoofMaterial, + } = useRoofAllocationSetting(id) return ( @@ -28,7 +39,13 @@ export default function RoofAllocationSetting(props) {
{getMessage('modal.roof.alloc.select.roof.material')}
- setSelectedRoofMaterial(e)} /> + { + const selected = roofMaterials.find((roofMaterial) => roofMaterial.roofMatlCd === e.id) + setCurrentRoofMaterial(selected) + }} + />
- {values.map((value, index) => ( -
-
- - -
-
-
-
-
- -
- {index === 0 && 基本屋根材} - {index !== 0 && } -
+ {roofList.map((roof, index) => { + return ( +
+
+ +
-
- {value.type === 'A' ? ( - <> +
+
+
+
+ r.id === roof.id)} + onChange={(e) => handleChangeRoofMaterial(e, index)} + /> +
+ {index === 0 && 基本屋根材} + {index !== 0 && } +
+
+
+ {roof.widAuth && (
W
@@ -68,6 +94,8 @@ export default function RoofAllocationSetting(props) {
+ )} + {roof.lenAuth && (
L
@@ -76,6 +104,8 @@ export default function RoofAllocationSetting(props) {
+ )} + {roof.raftAuth && (
{getMessage('modal.placement.initial.setting.rafter')}
@@ -84,9 +114,8 @@ export default function RoofAllocationSetting(props) {
- - ) : value.type === 'B' ? ( - <> + )} + {roof.roofPchAuth && (
{getMessage('hajebichi')}
@@ -95,63 +124,23 @@ export default function RoofAllocationSetting(props) {
-
- {getMessage('modal.placement.initial.setting.rafter')} -
- -
-
- - ) : value.type === 'C' ? ( - <> -
- {getMessage('hajebichi')} -
- -
-
- - ) : value.type === 'D' ? ( - <> -
- L -
- -
-
-
- {getMessage('modal.placement.initial.setting.rafter')} -
- -
-
- - ) : ( - '' - )} -
-
-
- - + )} +
+
+
+ + +
-
- ))} + ) + })}
@@ -218,7 +224,12 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
L
- +
diff --git a/src/components/floor-plan/modal/setting01/FirstOption.jsx b/src/components/floor-plan/modal/setting01/FirstOption.jsx index a9532efb..cfd9eea4 100644 --- a/src/components/floor-plan/modal/setting01/FirstOption.jsx +++ b/src/components/floor-plan/modal/setting01/FirstOption.jsx @@ -1,9 +1,8 @@ import React, { useEffect, useState } from 'react' -import { useCanvasSetting } from '@/hooks/option/useCanvasSetting' import { useMessage } from '@/hooks/useMessage' import { POLYGON_TYPE } from '@/common/common' -import { setSurfaceShapePattern } from '@/util/canvas-util' import { useEvent } from '@/hooks/useEvent' +import { useRoofFn } from '@/hooks/common/useRoofFn' export default function FirstOption(props) { const { getMessage } = useMessage() @@ -11,6 +10,7 @@ export default function FirstOption(props) { let { canvas, settingModalFirstOptions, setSettingModalFirstOptions, settingsData, setSettingsData, settingsDataSave, setSettingsDataSave } = props const { option1, option2, dimensionDisplay } = settingModalFirstOptions const { initEvent } = useEvent() + const { setSurfaceShapePattern } = useRoofFn() // 데이터를 최초 한 번만 조회 useEffect(() => { diff --git a/src/hooks/common/useCanvasConfigInitialize.js b/src/hooks/common/useCanvasConfigInitialize.js index 18d1a052..2fafbb4b 100644 --- a/src/hooks/common/useCanvasConfigInitialize.js +++ b/src/hooks/common/useCanvasConfigInitialize.js @@ -2,12 +2,13 @@ import { useEffect } from 'react' import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' import { basicSettingState, roofDisplaySelector, settingModalFirstOptionsState } from '@/store/settingAtom' import { canvasState, dotLineGridSettingState, pitchText, pitchTextSelector, showAngleUnitSelector } from '@/store/canvasAtom' -import { getChonByDegree, getDegreeByChon, setSurfaceShapePattern } from '@/util/canvas-util' +import { getChonByDegree, getDegreeByChon } from '@/util/canvas-util' import { useFont } from '@/hooks/common/useFont' import { useGrid } from '@/hooks/common/useGrid' import { globalFontAtom } from '@/store/fontAtom' import { useRoof } from '@/hooks/common/useRoof' import { usePolygon } from '@/hooks/usePolygon' +import { useRoofFn } from '@/hooks/common/useRoofFn' export function useCanvasConfigInitialize() { const canvas = useRecoilValue(canvasState) @@ -18,6 +19,7 @@ export function useCanvasConfigInitialize() { const setDotLineGridSetting = useSetRecoilState(dotLineGridSettingState) const pitchText = useRecoilValue(pitchTextSelector) const angleUnit = useRecoilValue(showAngleUnitSelector) + const { setSurfaceShapePattern } = useRoofFn() const {} = useFont() const {} = useGrid() const {} = useRoof() diff --git a/src/hooks/common/useRoof.js b/src/hooks/common/useRoof.js index 8aee0344..0b5e5a6b 100644 --- a/src/hooks/common/useRoof.js +++ b/src/hooks/common/useRoof.js @@ -2,12 +2,13 @@ import { canvasState } from '@/store/canvasAtom' import { allocDisplaySelector, roofDisplaySelector } from '@/store/settingAtom' import { useRecoilValue } from 'recoil' import { useEffect } from 'react' +import { useRoofFn } from '@/hooks/common/useRoofFn' export function useRoof() { const canvas = useRecoilValue(canvasState) const allocDisplay = useRecoilValue(allocDisplaySelector) const roofDisplay = useRecoilValue(roofDisplaySelector) - + const { setSurfaceShapePattern } = useRoofFn() useEffect(() => { if (!canvas) return canvas @@ -23,7 +24,7 @@ export function useRoof() { canvas.renderAll() }, [allocDisplay]) - const setSurfaceShapePattern = (polygon, mode = 'onlyBorder') => { + /*const setSurfaceShapePattern = (polygon, mode = 'onlyBorder') => { const ratio = window.devicePixelRatio || 1 let width = 265 / 10 @@ -145,7 +146,7 @@ export function useRoof() { polygon.set('fill', null) polygon.set('fill', pattern) polygon.canvas?.renderAll() - } + }*/ return {} } diff --git a/src/hooks/common/useRoofFn.js b/src/hooks/common/useRoofFn.js new file mode 100644 index 00000000..2e7e8160 --- /dev/null +++ b/src/hooks/common/useRoofFn.js @@ -0,0 +1,143 @@ +import { useRecoilValue } from 'recoil' +import { canvasState } from '@/store/canvasAtom' +import { selectedRoofMaterialSelector } from '@/store/settingAtom' + +export function useRoofFn() { + const canvas = useRecoilValue(canvasState) + const selectedRoofMaterial = useRecoilValue(selectedRoofMaterialSelector) + + //면형상 선택 클릭시 지붕 패턴 입히기 + function setSurfaceShapePattern(polygon, mode = 'onlyBorder', trestleMode = false) { + debugger + const ratio = window.devicePixelRatio || 1 + + let width = selectedRoofMaterial.width / 10 + let height = selectedRoofMaterial.length / 10 + let roofStyle = 2 + const inputPatternSize = { width: width, height: height } //임시 사이즈 + const patternSize = { ...inputPatternSize } // 입력된 값을 뒤집기 위해 + + if (polygon.direction === 'east' || polygon.direction === 'west') { + //세로형이면 width height를 바꿈 + ;[patternSize.width, patternSize.height] = [inputPatternSize.height, patternSize.width] + } + + // 패턴 소스를 위한 임시 캔버스 생성 + const patternSourceCanvas = document.createElement('canvas') + patternSourceCanvas.width = polygon.width * ratio + patternSourceCanvas.height = polygon.height * ratio + const ctx = patternSourceCanvas.getContext('2d') + let offset = roofStyle === 1 ? 0 : patternSize.width / 2 + + const rows = Math.floor(patternSourceCanvas.height / patternSize.height) + const cols = Math.floor(patternSourceCanvas.width / patternSize.width) + + ctx.strokeStyle = mode === 'allPainted' ? 'black' : 'green' + ctx.lineWidth = mode === 'allPainted' ? 1 : 0.4 + ctx.fillStyle = mode === 'allPainted' ? 'rgba(0, 159, 64, 0.7)' : 'white' + + if (trestleMode) { + ctx.strokeStyle = 'black' + ctx.lineWidth = 0.2 + ctx.fillStyle = 'rgba(0, 0, 0, 0.1)' + } else { + ctx.fillStyle = 'rgba(255, 255, 255, 1)' + } + + if (polygon.direction === 'east' || polygon.direction === 'west') { + offset = roofStyle === 1 ? 0 : patternSize.height / 2 + for (let col = 0; col <= cols; col++) { + const x = col * patternSize.width + const yStart = 0 + const yEnd = patternSourceCanvas.height + ctx.beginPath() + ctx.moveTo(x, yStart) // 선 시작점 + ctx.lineTo(x, yEnd) // 선 끝점 + ctx.stroke() + if (mode === 'allPainted' || trestleMode) { + ctx.fillRect(x, yStart, patternSize.width, yEnd - yStart) + } + + for (let row = 0; row <= rows; row++) { + const y = row * patternSize.height + (col % 2 === 0 ? 0 : offset) + const xStart = col * patternSize.width + const xEnd = xStart + patternSize.width + ctx.beginPath() + ctx.moveTo(xStart, y) // 선 시작점 + ctx.lineTo(xEnd, y) // 선 끝점 + ctx.stroke() + if (mode === 'allPainted' || trestleMode) { + ctx.fillRect(xStart, y, xEnd - xStart, patternSize.height) + } + } + } + } else { + for (let row = 0; row <= rows; row++) { + const y = row * patternSize.height + + ctx.beginPath() + ctx.moveTo(0, y) // 선 시작점 + ctx.lineTo(patternSourceCanvas.width, y) // 선 끝점 + ctx.stroke() + if (mode === 'allPainted' || trestleMode) { + ctx.fillRect(0, y, patternSourceCanvas.width, patternSize.height) + } + + for (let col = 0; col <= cols; col++) { + const x = col * patternSize.width + (row % 2 === 0 ? 0 : offset) + const yStart = row * patternSize.height + const yEnd = yStart + patternSize.height + + ctx.beginPath() + ctx.moveTo(x, yStart) // 선 시작점 + ctx.lineTo(x, yEnd) // 선 끝점 + ctx.stroke() + if (mode === 'allPainted' || trestleMode) { + ctx.fillRect(x, yStart, patternSize.width, yEnd - yStart) + } + } + } + } + + const hachingPatternSourceCanvas = document.createElement('canvas') + + if (mode === 'lineHatch') { + hachingPatternSourceCanvas.width = polygon.width * ratio + hachingPatternSourceCanvas.height = polygon.height * ratio + + const ctx1 = hachingPatternSourceCanvas.getContext('2d') + + const gap = 10 + + ctx1.strokeStyle = 'green' // 선 색상 + ctx1.lineWidth = 0.3 // 선 두께 + + for (let x = 0; x < hachingPatternSourceCanvas.width + hachingPatternSourceCanvas.height; x += gap) { + ctx1.beginPath() + ctx1.moveTo(x, 0) // 선 시작점 + ctx1.lineTo(0, x) // 선 끝점 + ctx1.stroke() + } + } + + const combinedPatternCanvas = document.createElement('canvas') + combinedPatternCanvas.width = polygon.width * ratio + combinedPatternCanvas.height = polygon.height * ratio + const combinedCtx = combinedPatternCanvas.getContext('2d') + + // 첫 번째 패턴을 그린 후 두 번째 패턴을 덧입힘 + combinedCtx.drawImage(patternSourceCanvas, 0, 0) + combinedCtx.drawImage(hachingPatternSourceCanvas, 0, 0) + + // 패턴 생성 + const pattern = new fabric.Pattern({ + source: combinedPatternCanvas, + repeat: 'repeat', + }) + + polygon.set('fill', null) + polygon.set('fill', pattern) + polygon.canvas?.renderAll() + } + return { setSurfaceShapePattern } +} diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index fea7dbf8..7f1560ce 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -1,6 +1,6 @@ import { useRecoilState, useRecoilValue } from 'recoil' import { canvasState } from '@/store/canvasAtom' -import { rectToPolygon, setSurfaceShapePattern } from '@/util/canvas-util' +import { rectToPolygon } from '@/util/canvas-util' import { roofDisplaySelector } from '@/store/settingAtom' import offsetPolygon, { calculateAngle } from '@/util/qpolygon-utils' import { QPolygon } from '@/components/fabric/QPolygon' @@ -13,6 +13,7 @@ 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' export function useModuleBasicSetting() { const canvas = useRecoilValue(canvasState) @@ -23,6 +24,7 @@ export function useModuleBasicSetting() { const { swalFire } = useSwal() const canvasSetting = useRecoilValue(canvasSettingState) const compasDeg = useRecoilValue(compasDegAtom) + const { setSurfaceShapePattern } = useRoofFn() // const { addTargetMouseEventListener, addCanvasMouseEventListener, initEvent } = useContext(EventContext) let selectedModuleInstSurfaceArray = [] diff --git a/src/hooks/object/useObjectBatch.js b/src/hooks/object/useObjectBatch.js index dd67b017..6fd858a1 100644 --- a/src/hooks/object/useObjectBatch.js +++ b/src/hooks/object/useObjectBatch.js @@ -5,13 +5,14 @@ import { useRecoilValue } from 'recoil' import { canvasState } from '@/store/canvasAtom' import { BATCH_TYPE, INPUT_TYPE } from '@/common/common' import { useEvent } from '@/hooks/useEvent' -import { pointsToTurfPolygon, polygonToTurfPolygon, rectToPolygon, setSurfaceShapePattern, triangleToPolygon } from '@/util/canvas-util' +import { pointsToTurfPolygon, polygonToTurfPolygon, rectToPolygon, triangleToPolygon } from '@/util/canvas-util' import { useSwal } from '@/hooks/useSwal' import * as turf from '@turf/turf' import { usePolygon } from '@/hooks/usePolygon' import { QPolygon } from '@/components/fabric/QPolygon' import { v4 as uuidv4 } from 'uuid' import { fontSelector } from '@/store/fontAtom' +import { useRoofFn } from '@/hooks/common/useRoofFn' export function useObjectBatch({ isHidden, setIsHidden }) { const { getMessage } = useMessage() @@ -20,6 +21,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) { // const { addCanvasMouseEventListener, initEvent, addDocumentEventListener } = useContext(EventContext) const { swalFire } = useSwal() const { drawDirectionArrow } = usePolygon() + const { setSurfaceShapePattern } = useRoofFn() const lengthTextFont = useRecoilValue(fontSelector('lengthText')) useEffect(() => { diff --git a/src/hooks/option/useCanvasSetting.js b/src/hooks/option/useCanvasSetting.js index 2a217956..499d15ea 100644 --- a/src/hooks/option/useCanvasSetting.js +++ b/src/hooks/option/useCanvasSetting.js @@ -21,6 +21,7 @@ import { basicSettingState, settingsState, roofMaterialsAtom, + selectedRoofMaterialSelector, } from '@/store/settingAtom' import { POLYGON_TYPE } from '@/common/common' import { globalFontAtom } from '@/store/fontAtom' @@ -28,6 +29,7 @@ import { dimensionLineSettingsState } from '@/store/commonUtilsAtom' import { gridColorState } from '@/store/gridAtom' import { useColor } from 'react-color-palette' import { useMasterController } from '@/hooks/common/useMasterController' +import { isObjectNotEmpty } from '@/util/common-utils' const defaultDotLineGridSetting = { INTERVAL: { @@ -92,7 +94,7 @@ export function useCanvasSetting() { const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState) const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState) - const { getRoofMaterialList } = useMasterController() + const { getRoofMaterialList, getModuleTypeItemList } = useMasterController() const [roofMaterials, setRoofMaterials] = useRecoilState(roofMaterialsAtom) const SelectOptions = [ @@ -102,18 +104,29 @@ export function useCanvasSetting() { { id: 4, name: '1/10', value: 1 / 10 }, ] + const selectedRoofMaterial = useRecoilValue(selectedRoofMaterialSelector) + useEffect(() => { addRoofMaterials() }, []) + useEffect(() => { + if (!selectedRoofMaterial || !isObjectNotEmpty(selectedRoofMaterial)) { + return + } + + const { id } = selectedRoofMaterial + console.log(getModuleTypeItemList(id)) + }, [selectedRoofMaterial]) + //지붕재 초기세팅 const addRoofMaterials = async () => { const { data } = await getRoofMaterialList() - const roofLists = data.map((item) => ({ + const roofLists = data.map((item, idx) => ({ ...item, id: item.roofMatlCd, name: item.roofMatlNm, - selected: false, + selected: idx === 0, nameJp: item.roofMatlNmJp, length: item.lenBase && parseInt(item.lenBase), width: item.widBase && parseInt(item.widBase), diff --git a/src/hooks/roofcover/useRoofAllocationSetting.js b/src/hooks/roofcover/useRoofAllocationSetting.js index 8ca6e8a1..ff20c0cb 100644 --- a/src/hooks/roofcover/useRoofAllocationSetting.js +++ b/src/hooks/roofcover/useRoofAllocationSetting.js @@ -1,7 +1,6 @@ import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' import { canvasState, currentMenuState, currentObjectState } from '@/store/canvasAtom' import { useEffect, useState } from 'react' -import { setSurfaceShapePattern } from '@/util/canvas-util' import { useSwal } from '@/hooks/useSwal' import { usePolygon } from '@/hooks/usePolygon' import { basicSettingState, roofDisplaySelector, roofMaterialsSelector, selectedRoofMaterialSelector } from '@/store/settingAtom' @@ -13,6 +12,7 @@ import { useMessage } from '@/hooks/useMessage' import useMenu from '@/hooks/common/useMenu' import { useCanvasMenu } from '@/hooks/common/useCanvasMenu' import { menuTypeState } from '@/store/menuAtom' +import { useRoofFn } from '@/hooks/common/useRoofFn' // 지붕면 할당 export function useRoofAllocationSetting(id) { @@ -33,6 +33,8 @@ export function useRoofAllocationSetting(id) { const [roofList, setRoofList] = useState([]) const [editingLines, setEditingLines] = useState([]) + const { setSurfaceShapePattern } = useRoofFn() + useEffect(() => { setRoofList(basicSetting.roofs) }, [basicSetting]) diff --git a/src/hooks/surface/usePlacementShapeDrawing.js b/src/hooks/surface/usePlacementShapeDrawing.js index 95388ca4..92f1e06b 100644 --- a/src/hooks/surface/usePlacementShapeDrawing.js +++ b/src/hooks/surface/usePlacementShapeDrawing.js @@ -13,7 +13,7 @@ import { useMouse } from '@/hooks/useMouse' import { useLine } from '@/hooks/useLine' import { useTempGrid } from '@/hooks/useTempGrid' import { useEffect, useRef } from 'react' -import { distanceBetweenPoints, setSurfaceShapePattern } from '@/util/canvas-util' +import { distanceBetweenPoints } from '@/util/canvas-util' import { fabric } from 'fabric' import { calculateAngle } from '@/util/qpolygon-utils' import { @@ -33,6 +33,7 @@ import { POLYGON_TYPE } from '@/common/common' import { usePopup } from '@/hooks/usePopup' import { roofDisplaySelector } from '@/store/settingAtom' +import { useRoofFn } from '@/hooks/common/useRoofFn' // 면형상 배치 export function usePlacementShapeDrawing(id) { @@ -46,6 +47,7 @@ export function usePlacementShapeDrawing(id) { const { addLine, removeLine } = useLine() const { addPolygonByLines, drawDirectionArrow } = usePolygon() const { tempGridMode } = useTempGrid() + const { setSurfaceShapePattern } = useRoofFn() const verticalHorizontalMode = useRecoilValue(verticalHorizontalModeState) const adsorptionPointAddMode = useRecoilValue(adsorptionPointAddModeState) diff --git a/src/hooks/surface/useSurfaceShapeBatch.js b/src/hooks/surface/useSurfaceShapeBatch.js index 844829d3..99eed453 100644 --- a/src/hooks/surface/useSurfaceShapeBatch.js +++ b/src/hooks/surface/useSurfaceShapeBatch.js @@ -3,7 +3,7 @@ import { useRecoilValue } from 'recoil' import { canvasState, globalPitchState } from '@/store/canvasAtom' import { MENU, POLYGON_TYPE } from '@/common/common' -import { getIntersectionPoint, setSurfaceShapePattern } from '@/util/canvas-util' +import { getIntersectionPoint } from '@/util/canvas-util' import { degreesToRadians } from '@turf/turf' import { QPolygon } from '@/components/fabric/QPolygon' import { useSwal } from '@/hooks/useSwal' @@ -15,6 +15,7 @@ import { usePolygon } from '@/hooks/usePolygon' import { fontSelector } from '@/store/fontAtom' import { slopeSelector } from '@/store/commonAtom' import { QLine } from '@/components/fabric/QLine' +import { useRoofFn } from '@/hooks/common/useRoofFn' export function useSurfaceShapeBatch() { const { getMessage } = useMessage() @@ -29,6 +30,7 @@ export function useSurfaceShapeBatch() { const { addCanvasMouseEventListener, initEvent } = useEvent() // const { addCanvasMouseEventListener, initEvent } = useContext(EventContext) const { closePopup } = usePopup() + const { setSurfaceShapePattern } = useRoofFn() const applySurfaceShape = (surfaceRefs, selectedType, id) => { let length1, length2, length3, length4, length5 diff --git a/src/store/settingAtom.js b/src/store/settingAtom.js index 443a14f3..8ad558f7 100644 --- a/src/store/settingAtom.js +++ b/src/store/settingAtom.js @@ -220,8 +220,7 @@ export const selectedRoofMaterialSelector = selector({ key: 'selectedRoofMaterialSelector', get: ({ get }) => { const basicSetting = get(basicSettingState) - const roofMaterials = get(roofMaterialsAtom) - return basicSetting.selectedRoofMaterial ?? roofMaterials[0] + return basicSetting.selectedRoofMaterial }, }) diff --git a/src/util/canvas-util.js b/src/util/canvas-util.js index b27f91db..82c72da0 100644 --- a/src/util/canvas-util.js +++ b/src/util/canvas-util.js @@ -792,7 +792,7 @@ export const rectToPolygon = (rect) => { } //면형상 선택 클릭시 지붕 패턴 입히기 -export function setSurfaceShapePattern(polygon, mode = 'onlyBorder', trestleMode = false) { +function setSurfaceShapePattern(polygon, mode = 'onlyBorder', trestleMode = false) { const ratio = window.devicePixelRatio || 1 let width = 265 / 10 From b38cbd39de1315fb14564b236c7757820f31958e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=8B=9D?= <43837214+Minsiki@users.noreply.github.com> Date: Tue, 17 Dec 2024 14:53:02 +0900 Subject: [PATCH 012/114] =?UTF-8?q?=EB=B0=B0=EC=B9=98=EB=A9=B4=20=EC=B4=88?= =?UTF-8?q?=EA=B8=B0=EC=84=A4=EC=A0=95,=20=EC=A7=80=EB=B6=95=EB=A9=B4=20?= =?UTF-8?q?=ED=95=A0=EB=8B=B9=20-=20=EC=A7=80=EB=B6=95=EC=9E=AC=20?= =?UTF-8?q?=EC=84=A0=ED=83=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../placementShape/PlacementShapeSetting.jsx | 76 ++++++++++++------- .../roofAllocation/RoofAllocationSetting.jsx | 51 ++++++++++--- 2 files changed, 90 insertions(+), 37 deletions(-) diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx index 66d7a8ec..b813472a 100644 --- a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx +++ b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx @@ -12,6 +12,7 @@ import { useRecoilValue } from 'recoil' import { roofMaterialsAtom } from '@/store/settingAtom' import { isObjectNotEmpty } from '@/util/common-utils' import { useCommonCode } from '@/hooks/common/useCommonCode' +import QSelectBox from '@/components/common/select/QSelectBox' export const ROOF_MATERIAL_LAYOUT = { PARALLEL: 'P', @@ -185,7 +186,17 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
-
+
+ {/* { + return { name: roof.roofMatlNm, value: roof.roofMatlCd } + })} + value={currentRoofMaterial.roofMatlCd} + onChange={(e) => { + handleRoofTypeChange(e) + }} + /> */} +
+ {/*
-
-
+
*/}
)} {['R', 'C'].includes(currentRoofMaterial.lenAuth) && (
-
- L -
- -
+ L +
+
+ {/*
+ +
*/}
)} {['C', 'R'].includes(currentRoofMaterial.raftAuth) && ( @@ -252,16 +277,15 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set )} {['C', 'R'].includes(currentRoofMaterial.roofPchAuth) && (
-
- {getMessage('hajebichi')} -
- -
+ {getMessage('hajebichi')} +
+
)} diff --git a/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx b/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx index 1477a89b..c0fbb2ba 100644 --- a/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx +++ b/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx @@ -8,6 +8,8 @@ import { contextPopupPositionState } from '@/store/popupAtom' import { useEffect, useState } from 'react' import { basicSettingState } from '@/store/settingAtom' import { ROOF_MATERIAL_LAYOUT } from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting' +import { useCanvasSetting } from '@/hooks/option/useCanvasSetting' +import { useCommonCode } from '@/hooks/common/useCommonCode' export default function RoofAllocationSetting(props) { const contextPopupPosition = useRecoilValue(contextPopupPositionState) @@ -24,7 +26,15 @@ export default function RoofAllocationSetting(props) { handleDefaultRoofMaterial, handleChangeRoofMaterial, } = useRoofAllocationSetting(id) - + const { fetchBasicSettings } = useCanvasSetting() + const { findCommonCode } = useCommonCode() + const [raftCodes, setRaftCodes] = useState([]) + useEffect(() => { + fetchBasicSettings() + const raftCodeList = findCommonCode('203800') + console.log('🚀 ~ useEffect ~ raftCodeList:', raftCodeList) + setRaftCodes(raftCodeList) + }, []) return (
@@ -88,41 +98,60 @@ export default function RoofAllocationSetting(props) { {roof.widAuth && (
W -
+
+ +
+ {/*
-
+
*/}
)} {roof.lenAuth && (
L -
+
+ +
+ {/*
-
+
*/}
)} {roof.raftAuth && (
{getMessage('modal.placement.initial.setting.rafter')} -
- +
+ ({ name: raft.clCodeNm, value: raft.clCode }))} + value={raftCodes.find((r) => r.id === roof.id)} + /> + {/* */}
)} {roof.roofPchAuth && (
{getMessage('hajebichi')} -
+
+ +
+ {/*
-
+
*/}
)}
From 9ab38ec8af964216b10b87e34acc8aaaec56d161 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Tue, 17 Dec 2024 17:20:01 +0900 Subject: [PATCH 013/114] =?UTF-8?q?=EC=A7=80=EB=B6=95=EC=9E=AC=20=EC=84=A0?= =?UTF-8?q?=ED=83=9D=20=EC=9E=91=EC=97=85=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../placementShape/PlacementShapeSetting.jsx | 24 +++++++++++++++---- .../roofAllocation/RoofAllocationSetting.jsx | 6 ++--- src/hooks/common/useRoofFn.js | 1 - src/hooks/option/useCanvasSetting.js | 5 ++++ 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx index b813472a..9c2ade43 100644 --- a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx +++ b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx @@ -28,11 +28,9 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set const { basicSetting, setBasicSettings, fetchBasicSettings, basicSettingSave } = useCanvasSetting() const { findCommonCode } = useCommonCode() const [raftCodes, setRaftCodes] = useState([]) - const [currentRoofMaterial, setCurrentRoofMaterial] = useState( - isObjectNotEmpty(basicSetting.selectedRoofMaterial) ? basicSetting.selectedRoofMaterial : roofMaterials[0], - ) + const [currentRoofMaterial, setCurrentRoofMaterial] = useState(basicSetting.selectedRoofMaterial) - const [roofLayout, setRoofLayout] = useState(ROOF_MATERIAL_LAYOUT.PARALLEL) + const [roofLayout, setRoofLayout] = useState(basicSetting.selectedRoofMaterial.layout) const roofRef = { roofCd: useRef(null), @@ -66,7 +64,6 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set selected: true, layout: roofLayout, } - console.log('roofInfo', roofInfo) const addedRoofs = [] addedRoofs.push(roofInfo) @@ -290,6 +287,23 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
)}
+
+
+ + +
+
diff --git a/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx b/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx index c0fbb2ba..17201bda 100644 --- a/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx +++ b/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx @@ -72,7 +72,7 @@ export default function RoofAllocationSetting(props) { return (
- +