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 { - 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 (['up', 'down'].includes(direction)) { + moduleLength = Number(modules[modules.length - 1].top) + Number(modules[modules.length - 1].height) - Number(modules[0].top) + } else if (['left', 'right'].includes(direction)) { + moduleLength = Number(modules[modules.length - 1].left) + Number(modules[modules.length - 1].width) - Number(modules[0].left) + } modules.forEach((module) => { - const { top, left } = getPosotion(module, direction, length, false) + const { top, left } = getPosotion(module, direction, Number(length) + Number(moduleLength), false) const moduleOptions = { ...module, left, top, id: uuidv4() } const rect = new QPolygon(module.getCurrentPoints(), moduleOptions) canvas.add(rect) @@ -530,12 +543,225 @@ export function useModule() { canvas.renderAll() } + const moduleColumnInsert = (type) => { + const activeModule = canvas.getObjects().filter((obj) => canvas.getActiveObjects()[0].id === obj.id)[0] + const columnModules = getColumnModules(activeModule) + 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 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 ? 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() + }) + 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) => { - 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 +827,7 @@ export function useModule() { moduleMultiCopy, moduleColumnRemove, moduleRowRemove, + moduleColumnInsert, + muduleRowInsert, } }