diff --git a/src/hooks/common/useTurf.js b/src/hooks/common/useTurf.js new file mode 100644 index 00000000..6696cd0a --- /dev/null +++ b/src/hooks/common/useTurf.js @@ -0,0 +1,37 @@ +import * as turf from '@turf/turf' + +export const useTurf = () => { + /** + * 배치면 안에 있는지 확인 + * @param {*} squarePolygon + * @param {*} turfModuleSetupSurface + * @param spare + * @returns + */ + const checkModuleDisjointSurface = (squarePolygon, turfModuleSetupSurface, spare = 1) => { + // 표면 영역을 spare만큼 수동 확장 + const expandedSurface = { + type: 'Polygon', + coordinates: [ + turfModuleSetupSurface.geometry.coordinates[0].map(([x, y]) => { + // 각 점을 바깥쪽으로 2 단위씩 이동 + const coords = turfModuleSetupSurface.geometry.coordinates[0] + const centerX = coords.slice(0, -1).reduce((sum, [x, y]) => sum + x, 0) / (coords.length - 1) + const centerY = coords.slice(0, -1).reduce((sum, [x, y]) => sum + y, 0) / (coords.length - 1) + + return [x < centerX ? x - spare : x + spare, y < centerY ? y - spare : y + spare] + }), + ], + } + + const isWithin = turf.booleanContains(expandedSurface, squarePolygon) || turf.booleanWithin(squarePolygon, expandedSurface) + + const isContact = turf.booleanIntersects(squarePolygon, expandedSurface) && !turf.booleanOverlap(squarePolygon, expandedSurface) + + return isWithin || isContact + } + + return { + checkModuleDisjointSurface, + } +} diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index 092c4e59..1546c2e0 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -34,6 +34,7 @@ import { isObjectNotEmpty } from '@/util/common-utils' import { useCircuitTrestle } from '@/hooks/useCirCuitTrestle' import { useMode } from '@/hooks/useMode' import { usePolygon } from '@/hooks/usePolygon' +import { useTurf } from '@/hooks/common/useTurf' export function useModuleBasicSetting(tabNum) { const canvas = useRecoilValue(canvasState) @@ -62,6 +63,8 @@ export function useModuleBasicSetting(tabNum) { const setManualSetupMode = useSetRecoilState(toggleManualSetupModeState) const setModuleRowColArray = useSetRecoilState(moduleRowColArrayState) + const { checkModuleDisjointSurface } = useTurf() + useEffect(() => { return () => { //수동 설치시 초기화 @@ -758,21 +761,21 @@ export function useModuleBasicSetting(tabNum) { //여기서부턴 배치면 설치 외곽선 라인 // 위쪽 변에 스냅 if (Math.abs(smallTop - trestleTop) < trestleSnapDistance) { - tempModule.top = trestleTop + 1 + tempModule.top = trestleTop } // 아래쪽 변에 스냅 if (Math.abs(smallBottom - trestleBottom) < trestleSnapDistance) { - tempModule.top = trestleTop + moduleSetupSurfaces[i].height - tempModule.height - 1 + tempModule.top = trestleTop + moduleSetupSurfaces[i].height - tempModule.height } // 왼쪽변에 스냅 if (Math.abs(smallLeft - trestleLeft) < trestleSnapDistance) { - tempModule.left = trestleLeft + 1 + tempModule.left = trestleLeft } //오른쪽 변에 스냅 if (Math.abs(smallRight - trestleRight) < trestleSnapDistance) { - tempModule.left = trestleRight - tempModule.width - 1 + tempModule.left = trestleRight - tempModule.width } if (flowDirection === 'south' || flowDirection === 'north') { @@ -869,7 +872,7 @@ export function useModuleBasicSetting(tabNum) { if (!isIntersection) return tempModule.setCoords() //좌표 재정렬 - if (turf.booleanContains(turfPolygon, tempTurfModule) || turf.booleanWithin(tempTurfModule, turfPolygon)) { + if (checkModuleDisjointSurface(tempTurfModule, turfPolygon)) { //마우스 클릭시 set으로 해당 위치에 셀을 넣음 const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module, true))) //겹치는지 확인 if (!isOverlap) { @@ -1426,7 +1429,7 @@ export function useModuleBasicSetting(tabNum) { const tempTurfModule = polygonToTurfPolygon(tempModule) tempModule.setCoords() //좌표 재정렬 - if (turf.booleanContains(turfPolygon, tempTurfModule) || turf.booleanWithin(tempTurfModule, turfPolygon)) { + if (checkModuleDisjointSurface(tempTurfModule, turfPolygon)) { //마우스 클릭시 set으로 해당 위치에 셀을 넣음 const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module))) //겹치는지 확인 if (!isOverlap) { @@ -1898,9 +1901,6 @@ export function useModuleBasicSetting(tabNum) { * @param {*} turfModuleSetupSurface * @returns */ - const checkModuleDisjointSurface = (squarePolygon, turfModuleSetupSurface) => { - return turf.booleanContains(turfModuleSetupSurface, squarePolygon) || turf.booleanWithin(squarePolygon, turfModuleSetupSurface) - } /** * 자동 레이아웃 설치 일시 row col 초과 여부 확인 @@ -2091,10 +2091,10 @@ export function useModuleBasicSetting(tabNum) { const moduleArray = [] let calcAreaWidth = Math.abs(flowLines.right.x1 - flowLines.left.x1) //오른쪽 x에서 왼쪽 x를 뺀 가운데를 찾는 로직 - let calcModuleWidthCount = calcAreaWidth / (width + intvHor + 1) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 + let calcModuleWidthCount = calcAreaWidth / (width + intvHor) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 let calcAreaHeight = flowLines.bottom.y1 - flowLines.top.y1 - let calcModuleHeightCount = calcAreaHeight / (height + intvVer + 1) + let calcModuleHeightCount = calcAreaHeight / (height + intvVer) if (type === MODULE_SETUP_TYPE.LAYOUT) { calcModuleWidthCount = layoutCol > calcModuleWidthCount ? calcModuleWidthCount : layoutCol @@ -2124,7 +2124,7 @@ export function useModuleBasicSetting(tabNum) { for (let i = 0; i < calcModuleHeightCount; i++) { let isInstall = false - let moduleY = flowLines.bottom.y1 - height * i - 1 //살짝 여유를 준다 + let moduleY = flowLines.bottom.y1 - height * i //살짝 여유를 준다 //두번째 모듈 -> 혼합일 경우의 설치될 모듈 높이를 계산 if (installedModuleHeightCount > 0) { @@ -2135,7 +2135,7 @@ export function useModuleBasicSetting(tabNum) { heightMargin = installedModuleHeightCount === 0 ? 0 : intvVer for (let j = 0; j < totalModuleWidthCount; j++) { - let moduleX = startPointX + width * j + 1 //5정도 마진을 준다 + let moduleX = startPointX + width * j //5정도 마진을 준다 widthMargin = j === 0 ? 0 : intvHor * j // 가로 마진값 chidoriLength = 0 //치도리가 아니여도 기본값을 5정도 준다 if (isChidori) { @@ -2277,9 +2277,9 @@ export function useModuleBasicSetting(tabNum) { const moduleArray = [] let calcAreaWidth = flowLines.right.x1 - flowLines.left.x1 //오른쪽 x에서 왼쪽 x를 뺀 가운데를 찾는 로직 - let calcModuleWidthCount = calcAreaWidth / (width + intvHor + 1) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 + let calcModuleWidthCount = calcAreaWidth / (width + intvHor) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 let calcAreaHeight = flowLines.bottom.y1 - flowLines.top.y1 - let calcModuleHeightCount = calcAreaHeight / (height + intvVer + 1) + let calcModuleHeightCount = calcAreaHeight / (height + intvVer) //단수지정 자동이면 if (type === MODULE_SETUP_TYPE.LAYOUT) { @@ -2319,7 +2319,7 @@ export function useModuleBasicSetting(tabNum) { heightMargin = installedModuleHeightCount === 0 ? 0 : intvVer //모듈간에 마진이 있어 마진값도 넣음 for (let j = 0; j < totalModuleWidthCount; j++) { //모듈 열수 만큼 반복 - let moduleX = startPointX - width * j - 1 //시작점에서 우 -> 좌로 그려 내려간다 + let moduleX = startPointX - width * j //시작점에서 우 -> 좌로 그려 내려간다 widthMargin = j === 0 ? 0 : intvHor * j chidoriLength = 0 if (isChidori && !isMaxSetup) { @@ -2460,10 +2460,10 @@ export function useModuleBasicSetting(tabNum) { const moduleArray = [] - let calcAreaWidth = flowLines.bottom.y1 - flowLines.top.y1 //아래에서 y에서 위를 y를 뺀 가운데를 찾는 로직 - let calcModuleWidthCount = calcAreaWidth / (height + intvHor + 1) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 - let calcAreaHeight = flowLines.right.x1 - flowLines.left.x1 - let calcModuleHeightCount = calcAreaHeight / (width + intvVer + 1) + let calcAreaWidth = Math.abs(flowLines.bottom.y1 - flowLines.top.y1) //아래에서 y에서 위를 y를 뺀 가운데를 찾는 로직 + let calcModuleWidthCount = calcAreaWidth / (height + intvHor) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 + let calcAreaHeight = Math.abs(flowLines.right.x1 - flowLines.left.x1) + let calcModuleHeightCount = calcAreaHeight / (width + intvVer) //단수지정 자동이면 if (type === MODULE_SETUP_TYPE.LAYOUT) { @@ -2490,12 +2490,12 @@ export function useModuleBasicSetting(tabNum) { //첫번재 모듈 설치 후 두번째 모듈을 몇개까지 설치 할 수 있는지 계산 if (moduleIndex > 0) { moduleMaxRows = totalModuleMaxRows - installedModuleHeightCount //두번째 모듈일때 - isChidoriLine = installedModuleHeightCount % 2 != 0 ? true : false //첫번째에서 짝수에서 끝났으면 홀수는 치도리가 아님 짝수는 치도리 + isChidoriLine = installedModuleHeightCount % 2 !== 0 //첫번째에서 짝수에서 끝났으면 홀수는 치도리가 아님 짝수는 치도리 } for (let i = 0; i < calcModuleHeightCount; i++) { let isInstall = false - let moduleY = flowLines.left.x1 + width * i + 1 //살짝 여유를 준다 + let moduleY = flowLines.left.x1 + width * i //살짝 여유를 준다 //두번째 모듈 -> 혼합일 경우의 설치될 모듈 높이를 계산 if (installedModuleHeightCount > 0) { @@ -2506,11 +2506,11 @@ export function useModuleBasicSetting(tabNum) { heightMargin = installedModuleHeightCount === 0 ? 0 : intvHor for (let j = 0; j < totalModuleWidthCount; j++) { - let moduleX = startPointX + height * j + 1 //5정도 마진을 준다 + let moduleX = startPointX + height * j //5정도 마진을 준다 widthMargin = j === 0 ? 0 : intvVer * j // 가로 마진값 chidoriLength = 0 //치도리가 아니여도 기본값을 5정도 준다 if (isChidori && !isMaxSetup) { - chidoriLength = installedModuleHeightCount % 2 == 0 ? 0 : height / 2 - intvVer + chidoriLength = installedModuleHeightCount % 2 === 0 ? 0 : height / 2 - intvVer } let square = [ @@ -2527,8 +2527,8 @@ export function useModuleBasicSetting(tabNum) { moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id, moduleInfo: module } let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) - - let disjointFromTrestle = checkModuleDisjointSurface(squarePolygon, polygonToTurfPolygon(moduleSetupSurface, true)) + let turfSurface = polygonToTurfPolygon(moduleSetupSurface, true) + let disjointFromTrestle = checkModuleDisjointSurface(squarePolygon, turfSurface) let isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) if (disjointFromTrestle && isDisjoint) { @@ -2546,9 +2546,9 @@ export function useModuleBasicSetting(tabNum) { installedLastHeightCoord = moduleY + width + widthMargin } else { //디버깅용 - // tempModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) - // canvas?.add(tempModule) - // canvas.renderAll() + /*tempModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) + canvas?.add(tempModule) + canvas.renderAll()*/ } } @@ -2643,9 +2643,9 @@ export function useModuleBasicSetting(tabNum) { const moduleArray = [] let calcAreaWidth = flowLines.bottom.y1 - flowLines.top.y1 //아래에서 y에서 위를 y를 뺀 가운데를 찾는 로직 - let calcModuleWidthCount = calcAreaWidth / (height + intvHor + 1) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 + let calcModuleWidthCount = calcAreaWidth / (height + intvHor) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 let calcAreaHeight = flowLines.right.x1 - flowLines.left.x1 - let calcModuleHeightCount = calcAreaHeight / (width + intvVer + 1) + let calcModuleHeightCount = calcAreaHeight / (width + intvVer) //단수지정 자동이면 if (type === MODULE_SETUP_TYPE.LAYOUT) { @@ -2677,7 +2677,7 @@ export function useModuleBasicSetting(tabNum) { for (let i = 0; i < calcModuleHeightCount; i++) { let isInstall = false - let moduleY = flowLines.right.x1 - width * i - 1 //살짝 여유를 준다 + let moduleY = flowLines.right.x1 - width * i //살짝 여유를 준다 //두번째 모듈 -> 혼합일 경우의 설치될 모듈 높이를 계산 if (installedModuleHeightCount > 0) { @@ -2688,7 +2688,7 @@ export function useModuleBasicSetting(tabNum) { heightMargin = installedModuleHeightCount === 0 ? 0 : intvHor for (let j = 0; j < totalModuleWidthCount; j++) { - let moduleX = startPointX - height * j - 1 //5정도 마진을 준다 + let moduleX = startPointX - height * j //5정도 마진을 준다 widthMargin = j === 0 ? 0 : intvVer * j // 가로 마진값 chidoriLength = 0 //치도리가 아니여도 기본값을 5정도 준다 if (isChidori && !isMaxSetup) { @@ -3414,21 +3414,21 @@ export function useModuleBasicSetting(tabNum) { // 위쪽 변에 스냅 if (Math.abs(smallTop - trestleTop) < trestleSnapDistance) { - tempModule.top = trestleTop + 1 + tempModule.top = trestleTop } // 아래쪽 변에 스냅 if (Math.abs(smallBottom - trestleBottom) < trestleSnapDistance) { - tempModule.top = trestleTop + moduleSetupSurfaces[i].height - tempModule.height - 1 + tempModule.top = trestleTop + moduleSetupSurfaces[i].height - tempModule.height } // 왼쪽변에 스냅 if (Math.abs(smallLeft - trestleLeft) < trestleSnapDistance) { - tempModule.left = trestleLeft + 1 + tempModule.left = trestleLeft } //오른쪽 변에 스냅 if (Math.abs(smallRight - trestleRight) < trestleSnapDistance) { - tempModule.left = trestleRight - tempModule.width - 1 + tempModule.left = trestleRight - tempModule.width } if (flowDirection === 'south' || flowDirection === 'north') { @@ -3705,16 +3705,6 @@ export function useModuleBasicSetting(tabNum) { return containsBatchObjects } - /** - * 배치면 안에 있는지 확인 - * @param {*} squarePolygon - * @param {*} turfModuleSetupSurface - * @returns - */ - const checkModuleDisjointSurface = (squarePolygon, turfModuleSetupSurface) => { - return turf.booleanContains(turfModuleSetupSurface, squarePolygon) || turf.booleanWithin(squarePolygon, turfModuleSetupSurface) - } - const flatRoofDownFlowSetupModule = ( surfaceMaxLines, maxLengthLine,