From 860ddec138a0e1a623f0fb45f7efd1098919a38b 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: Mon, 30 Dec 2024 10:55:13 +0900 Subject: [PATCH 1/2] module copy, move --- .../modal/module/column/ColumnInsert.jsx | 32 ++++++--- src/hooks/module/useModule.js | 65 ++++++++++++++++++- 2 files changed, 86 insertions(+), 11 deletions(-) diff --git a/src/components/floor-plan/modal/module/column/ColumnInsert.jsx b/src/components/floor-plan/modal/module/column/ColumnInsert.jsx index 8239dc33..56f9a66c 100644 --- a/src/components/floor-plan/modal/module/column/ColumnInsert.jsx +++ b/src/components/floor-plan/modal/module/column/ColumnInsert.jsx @@ -5,20 +5,22 @@ import { usePopup } from '@/hooks/usePopup' import { useMessage } from '@/hooks/useMessage' import { useState } from 'react' import Image from 'next/image' +import { MODULE_INSERT_TYPE, useModule } from '@/hooks/module/useModule' export default function ColumnInsert(props) { const contextPopupPosition = useRecoilValue(contextPopupPositionState) const { id, pos = contextPopupPosition, apply } = props const { closePopup } = usePopup() - const [selectedType, setSelectedType] = useState(1) + const [selectedType, setSelectedType] = useState(MODULE_INSERT_TYPE.LEFT) const { getMessage } = useMessage() + const { moduleColumnInsert } = useModule() const handleApply = () => { - if (apply) apply() + moduleColumnInsert(selectedType) closePopup(id) } - const HandleRadioChange = (e) => { - setSelectedType(Number(e.target.value)) + const handleRadioChange = (e) => { + setSelectedType(e.target.value) } return ( @@ -36,16 +38,30 @@ export default function ColumnInsert(props) {
- +
- +
- {selectedType === 1 && ( + {selectedType === MODULE_INSERT_TYPE.LEFT && ( react )} - {selectedType === 2 && ( + {selectedType === MODULE_INSERT_TYPE.RIGHT && ( react obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.id === modules[0].surfaceId)[0] let [isOverlapOtherModules, isOverlapObjects, isOutsideSurface] = [[], [], []] + let moduleLength = 0 + if (type === 'column') { + moduleLength = Number(modules[modules.length - 1].top) + Number(modules[modules.length - 1].height) - Number(modules[0].top) + } else if (type === 'row') { + moduleLength = Number(modules[modules.length - 1].left) + Number(modules[modules.length - 1].width) - Number(modules[0].left) + } + console.log('🚀 ~ moduleMultiCopy ~ modules:', modules) + console.log('🚀 ~ moduleMultiCopy ~ moduleLength:', moduleLength) modules.forEach((module) => { - const { top, left } = getPosotion(module, direction, length, false) + const { top, left } = getPosotion(module, direction, Number(length) + Number(moduleLength), false) + console.log('🚀 ~ modules.forEach ~ top:', top) const moduleOptions = { ...module, left, top, id: uuidv4() } const rect = new QPolygon(module.getCurrentPoints(), moduleOptions) canvas.add(rect) @@ -529,13 +545,55 @@ export function useModule() { } canvas.renderAll() } + // 좌우 열 옮기고 current Column 복사하기. + const moduleColumnInsert = (type) => { + const activeModule = canvas.getObjects().filter((obj) => canvas.getActiveObjects()[0].id === obj.id)[0] + const columnModules = getColumnModules(activeModule) + const otherModules = getOtherModules(columnModules) + const targetModules = + type === MODULE_INSERT_TYPE.LEFT + ? otherModules.filter((module) => module.left < activeModule.left).sort((a, b) => a.left - b.left) + : otherModules.filter((module) => module.left > activeModule.left).sort((a, b) => b.left - a.left) + const objects = getObjects() + const copyRects = [] + const moduleSetupSurface = canvas + .getObjects() + .filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.id === activeModule.surfaceId)[0] + let width = -1 + let [isOverlapOtherModules, isOverlapObjects, isOutsideSurface] = [[], [], []] + + targetModules.forEach((module) => { + if (width === -1) width = type === MODULE_INSERT_TYPE.LEFT ? module.left - activeModule.left : activeModule.left - module.left + const { left } = getPosotion(module, type, width, false) + const moduleOptions = { ...module, left, top, id: uuidv4() } + module.set({ left }) + // const rect = new QPolygon(module.getCurrentPoints(), moduleOptions) + // canvas.add(rect) + // copyRects.push(rect) + module.setCoords() + }) + // columnModules.forEach((module) => { + // const { top, left } = getPosotion(module, MODULE_INSERT_TYPE.LEFT, module.width, false) + // const moduleOptions = { ...module, left, top, id: uuidv4() } + // const rect = new QPolygon(module.getCurrentPoints(), moduleOptions) + // canvas.add(rect) + // copyRects.push(rect) + // module.setCoords() + // }) + } const getRowModules = (target) => { - return canvas.getObjects().filter((obj) => target.surfaceId === obj.surfaceId && obj.name === POLYGON_TYPE.MODULE && obj.top === target.top) + return canvas + .getObjects() + .filter((obj) => target.surfaceId === obj.surfaceId && obj.name === POLYGON_TYPE.MODULE && obj.top === target.top) + .sort((a, b) => a.left - b.left) } const getColumnModules = (target) => { - return canvas.getObjects().filter((obj) => target.surfaceId === obj.surfaceId && obj.name === POLYGON_TYPE.MODULE && obj.left === target.left) + return canvas + .getObjects() + .filter((obj) => target.surfaceId === obj.surfaceId && obj.name === POLYGON_TYPE.MODULE && obj.left === target.left) + .sort((a, b) => a.top - b.top) } const getPosotion = (target, direction, length, hasMargin = false) => { @@ -601,5 +659,6 @@ export function useModule() { moduleMultiCopy, moduleColumnRemove, moduleRowRemove, + moduleColumnInsert, } } From 3907624dac96a284a84cb8b43d952453b23bfd9c 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: Mon, 30 Dec 2024 15:13:11 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=EC=97=B4.=20=EB=8B=A8=20=EC=82=BD=EC=9E=85?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../floor-plan/modal/module/row/RowInsert.jsx | 30 ++- src/hooks/module/useModule.js | 221 +++++++++++++++--- 2 files changed, 218 insertions(+), 33 deletions(-) diff --git a/src/components/floor-plan/modal/module/row/RowInsert.jsx b/src/components/floor-plan/modal/module/row/RowInsert.jsx index 42ce1a31..613fb180 100644 --- a/src/components/floor-plan/modal/module/row/RowInsert.jsx +++ b/src/components/floor-plan/modal/module/row/RowInsert.jsx @@ -5,20 +5,22 @@ import { useRecoilValue } from 'recoil' import { contextPopupPositionState } from '@/store/popupAtom' import { usePopup } from '@/hooks/usePopup' import { useMessage } from '@/hooks/useMessage' +import { MODULE_INSERT_TYPE, useModule } from '@/hooks/module/useModule' export default function RowInsert(props) { const contextPopupPosition = useRecoilValue(contextPopupPositionState) const { id, pos = contextPopupPosition, apply } = props const { closePopup } = usePopup() - const [selectedType, setSelectedType] = useState(1) + const [selectedType, setSelectedType] = useState(MODULE_INSERT_TYPE.TOP) const { getMessage } = useMessage() + const { muduleRowInsert } = useModule() const handleApply = () => { - if (apply) apply() + muduleRowInsert(selectedType) closePopup(id) } const HandleRadioChange = (e) => { - setSelectedType(Number(e.target.value)) + setSelectedType(e.target.value) } return ( @@ -36,16 +38,30 @@ export default function RowInsert(props) {
- +
- +
- {selectedType === 1 && ( + {selectedType === MODULE_INSERT_TYPE.TOP && ( react )} - {selectedType === 2 && ( + {selectedType === MODULE_INSERT_TYPE.BOTTOM && ( react obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.id === modules[0].surfaceId)[0] let [isOverlapOtherModules, isOverlapObjects, isOutsideSurface] = [[], [], []] let moduleLength = 0 - if (type === 'column') { + if (['up', 'down'].includes(direction)) { moduleLength = Number(modules[modules.length - 1].top) + Number(modules[modules.length - 1].height) - Number(modules[0].top) - } else if (type === 'row') { + } else if (['left', 'right'].includes(direction)) { moduleLength = Number(modules[modules.length - 1].left) + Number(modules[modules.length - 1].width) - Number(modules[0].left) } - console.log('🚀 ~ moduleMultiCopy ~ modules:', modules) - console.log('🚀 ~ moduleMultiCopy ~ moduleLength:', moduleLength) modules.forEach((module) => { const { top, left } = getPosotion(module, direction, Number(length) + Number(moduleLength), false) - console.log('🚀 ~ modules.forEach ~ top:', top) const moduleOptions = { ...module, left, top, id: uuidv4() } const rect = new QPolygon(module.getCurrentPoints(), moduleOptions) canvas.add(rect) @@ -545,41 +542,212 @@ export function useModule() { } canvas.renderAll() } - // 좌우 열 옮기고 current Column 복사하기. + const moduleColumnInsert = (type) => { const activeModule = canvas.getObjects().filter((obj) => canvas.getActiveObjects()[0].id === obj.id)[0] const columnModules = getColumnModules(activeModule) - const otherModules = getOtherModules(columnModules) + let otherModules = getOtherModules(columnModules) const targetModules = type === MODULE_INSERT_TYPE.LEFT ? otherModules.filter((module) => module.left < activeModule.left).sort((a, b) => a.left - b.left) : otherModules.filter((module) => module.left > activeModule.left).sort((a, b) => b.left - a.left) const objects = getObjects() - const copyRects = [] + const copyModules = [] const moduleSetupSurface = canvas .getObjects() .filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.id === activeModule.surfaceId)[0] let width = -1 let [isOverlapOtherModules, isOverlapObjects, isOutsideSurface] = [[], [], []] - + if (targetModules.length === 0) { + swalFire({ + title: '마지막 모듈입니다.', + icon: 'error', + type: 'alert', + }) + return + } + canvas.discardActiveObject() targetModules.forEach((module) => { - if (width === -1) width = type === MODULE_INSERT_TYPE.LEFT ? module.left - activeModule.left : activeModule.left - module.left - const { left } = getPosotion(module, type, width, false) - const moduleOptions = { ...module, left, top, id: uuidv4() } - module.set({ left }) - // const rect = new QPolygon(module.getCurrentPoints(), moduleOptions) - // canvas.add(rect) - // copyRects.push(rect) + if (width === -1) + width = type === MODULE_INSERT_TYPE.LEFT ? Number(activeModule.left) - Number(module.left) : Number(module.left) - Number(activeModule.left) + const { top, left } = getPosotion(module, type, width, false) + module.originPos = { + left: module.left, + top: module.top, + } + module.set({ left, top }) + canvas.renderAll() + if (objects.length > 0) { + isOverlapObjects.push(!checkModuleDisjointObjects(polygonToTurfPolygon(module, true), objects)) + } + + isOutsideSurface.push( + !turf.booleanContains(polygonToTurfPolygon(moduleSetupSurface, true), polygonToTurfPolygon(module, true)) || + !turf.booleanWithin(polygonToTurfPolygon(module, true), polygonToTurfPolygon(moduleSetupSurface, true)), + ) module.setCoords() }) - // columnModules.forEach((module) => { - // const { top, left } = getPosotion(module, MODULE_INSERT_TYPE.LEFT, module.width, false) - // const moduleOptions = { ...module, left, top, id: uuidv4() } - // const rect = new QPolygon(module.getCurrentPoints(), moduleOptions) - // canvas.add(rect) - // copyRects.push(rect) - // module.setCoords() - // }) + otherModules = getOtherModules(columnModules) + columnModules.forEach((module) => { + const { top, left } = getPosotion(module, type, width, false) + const moduleOptions = { ...module, left, top, id: uuidv4() } + const copyModule = new QPolygon(module.points, moduleOptions) + canvas.add(copyModule) + copyModules.push(copyModule) + canvas.renderAll() + + if (otherModules.length > 0) { + isOverlapOtherModules.push( + otherModules.some( + (otherModule) => + turf.booleanOverlap(polygonToTurfPolygon(copyModule, true), polygonToTurfPolygon(otherModule, true)) || + turf.booleanWithin(polygonToTurfPolygon(copyModule, true), polygonToTurfPolygon(otherModule, true)), + ), + ) + } + + if (objects.length > 0) { + isOverlapObjects.push(!checkModuleDisjointObjects(polygonToTurfPolygon(module, true), objects)) + } + + isOutsideSurface.push( + !turf.booleanContains(polygonToTurfPolygon(moduleSetupSurface, true), polygonToTurfPolygon(copyModule, true)) || + !turf.booleanWithin(polygonToTurfPolygon(copyModule, true), polygonToTurfPolygon(moduleSetupSurface, true)), + ) + module.setCoords() + }) + + if ( + isOverlapOtherModules.some((isOverlap) => isOverlap) || + isOverlapObjects.some((isOverlap) => isOverlap) || + isOutsideSurface.some((isOutside) => isOutside) + ) { + swalFire({ + title: isOverlapOtherModules.some((isOverlap) => isOverlap) + ? '겹치는 모듈이 있습니다.' + : isOverlapObjects.some((isOverlap) => isOverlap) + ? '모듈이 오브젝트와 겹칩니다.' + : '영역 밖', + icon: 'error', + type: 'confirm', + confirmFn: () => { + targetModules.forEach((module) => { + module.set({ top: module.originPos.top, left: module.originPos.left }) + module.setCoords() + }) + canvas.renderAll() + copyModules.forEach((module) => { + canvas.remove(module) + }) + canvas.renderAll() + }, + }) + } + } + + const muduleRowInsert = (type) => { + console.log('🚀 ~ muduleRowInsert ~ type:', type) + const activeModule = canvas.getObjects().filter((obj) => canvas.getActiveObjects()[0].id === obj.id)[0] + const rowModules = getRowModules(activeModule) + console.log('🚀 ~ muduleRowInsert ~ rowModules:', rowModules) + let otherModules = getOtherModules(rowModules) + const targetModules = + type === MODULE_INSERT_TYPE.TOP + ? otherModules.filter((module) => module.top < activeModule.top).sort((a, b) => b.top - a.top) + : otherModules.filter((module) => module.top > activeModule.top).sort((a, b) => a.top - b.top) + console.log('🚀 ~ muduleRowInsert ~ targetModules:', targetModules) + if (targetModules.length === 0) { + swalFire({ + title: '마지막 모듈입니다.', + icon: 'error', + type: 'alert', + }) + return + } + const objects = getObjects() + const copyModules = [] + const moduleSetupSurface = canvas + .getObjects() + .filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.id === activeModule.surfaceId)[0] + let height = -1 + let [isOverlapOtherModules, isOverlapObjects, isOutsideSurface] = [[], [], []] + canvas.discardActiveObject() + targetModules.forEach((module) => { + if (height === -1) + height = type === MODULE_INSERT_TYPE.TOP ? Number(activeModule.top) - Number(module.top) : Number(module.top) - Number(activeModule.top) + const { top, left } = getPosotion(module, type, height, false) + module.originPos = { + left: module.left, + top: module.top, + } + module.set({ left, top }) + canvas.renderAll() + if (objects.length > 0) { + isOverlapObjects.push(!checkModuleDisjointObjects(polygonToTurfPolygon(module, true), objects)) + } + + isOutsideSurface.push( + !turf.booleanContains(polygonToTurfPolygon(moduleSetupSurface, true), polygonToTurfPolygon(module, true)) || + !turf.booleanWithin(polygonToTurfPolygon(module, true), polygonToTurfPolygon(moduleSetupSurface, true)), + ) + module.setCoords() + }) + otherModules = getOtherModules(rowModules) + rowModules.forEach((module) => { + const { top, left } = getPosotion(module, type, height, false) + const moduleOptions = { ...module, left, top, id: uuidv4() } + const copyModule = new QPolygon(module.points, moduleOptions) + canvas.add(copyModule) + copyModules.push(copyModule) + canvas.renderAll() + + if (otherModules.length > 0) { + isOverlapOtherModules.push( + otherModules.some( + (otherModule) => + turf.booleanOverlap(polygonToTurfPolygon(copyModule, true), polygonToTurfPolygon(otherModule, true)) || + turf.booleanWithin(polygonToTurfPolygon(copyModule, true), polygonToTurfPolygon(otherModule, true)), + ), + ) + } + + if (objects.length > 0) { + isOverlapObjects.push(!checkModuleDisjointObjects(polygonToTurfPolygon(module, true), objects)) + } + + isOutsideSurface.push( + !turf.booleanContains(polygonToTurfPolygon(moduleSetupSurface, true), polygonToTurfPolygon(copyModule, true)) || + !turf.booleanWithin(polygonToTurfPolygon(copyModule, true), polygonToTurfPolygon(moduleSetupSurface, true)), + ) + module.setCoords() + }) + + if ( + isOverlapOtherModules.some((isOverlap) => isOverlap) || + isOverlapObjects.some((isOverlap) => isOverlap) || + isOutsideSurface.some((isOutside) => isOutside) + ) { + swalFire({ + title: isOverlapOtherModules.some((isOverlap) => isOverlap) + ? '겹치는 모듈이 있습니다.' + : isOverlapObjects.some((isOverlap) => isOverlap) + ? '모듈이 오브젝트와 겹칩니다.' + : '영역 밖', + icon: 'error', + type: 'confirm', + confirmFn: () => { + targetModules.forEach((module) => { + module.set({ top: module.originPos.top, left: module.originPos.left }) + module.setCoords() + }) + canvas.renderAll() + copyModules.forEach((module) => { + canvas.remove(module) + }) + canvas.renderAll() + }, + }) + } } const getRowModules = (target) => { @@ -660,5 +828,6 @@ export function useModule() { moduleColumnRemove, moduleRowRemove, moduleColumnInsert, + muduleRowInsert, } }