diff --git a/src/components/floor-plan/modal/basic/step/pitch/PitchModule.jsx b/src/components/floor-plan/modal/basic/step/pitch/PitchModule.jsx index 39d0ee19..e248c272 100644 --- a/src/components/floor-plan/modal/basic/step/pitch/PitchModule.jsx +++ b/src/components/floor-plan/modal/basic/step/pitch/PitchModule.jsx @@ -47,17 +47,17 @@ export default function PitchModule({}) { setSelectedModules(option) //선택값 저장 setModuleSelectionData({ ...moduleSelectionData, - flatModule: option, + module: option, }) moduleSelectedDataTrigger({ ...moduleSelectionData, - flatModule: option, + module: option, }) } useEffect(() => { - if (isObjectNotEmpty(moduleSelectionData.flatModule) && moduleList.length > 0) { - handleChangeModule(moduleSelectionData.flatModule) + if (isObjectNotEmpty(moduleSelectionData.module) && moduleList.length > 0) { + handleChangeModule(moduleSelectionData.module) } }, [moduleList]) 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 64d91881..b4137ac6 100644 --- a/src/components/floor-plan/modal/basic/step/pitch/PitchPlacement.jsx +++ b/src/components/floor-plan/modal/basic/step/pitch/PitchPlacement.jsx @@ -69,7 +69,7 @@ const PitchPlacement = forwardRef((props, refs) => { excretaLine.forEach((line) => { line.set({ stroke: '#642EFB', - strokeWidth: 5, + strokeWidth: 3, surfaceId: surface.surfaceId, name: 'flatExcretaLine', }) @@ -89,10 +89,10 @@ const PitchPlacement = forwardRef((props, refs) => { } useEffect(() => { - if (!moduleSelectionData.flatModule) return // null 오류 차단 로직 추가 - if (moduleSelectionData && moduleSelectionData.flatModule.itemList.length > 0) { + if (!moduleSelectionData.module) return // null 오류 차단 로직 추가 + if (moduleSelectionData && moduleSelectionData.module.itemList.length > 0) { let initCheckedModule = {} - moduleSelectionData.flatModule.itemList.forEach((obj, index) => { + moduleSelectionData.module.itemList.forEach((obj, index) => { if (index === 0) { initCheckedModule = { [obj.itemId]: true } } else { diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index 7d99f9b1..d96b96a1 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -3,7 +3,7 @@ import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' import { canvasSettingState, canvasState, checkedModuleState, currentObjectState, isManualModuleSetupState } from '@/store/canvasAtom' import { rectToPolygon, polygonToTurfPolygon, calculateVisibleModuleHeight, getDegreeByChon } from '@/util/canvas-util' import { addedRoofsState, basicSettingState, roofDisplaySelector } from '@/store/settingAtom' -import offsetPolygon, { calculateAngle } from '@/util/qpolygon-utils' +import offsetPolygon, { calculateAngle, createLinesFromPolygon } from '@/util/qpolygon-utils' import { QPolygon } from '@/components/fabric/QPolygon' import { moduleSetupSurfaceState, moduleIsSetupState } from '@/store/canvasAtom' import { useEvent } from '@/hooks/useEvent' @@ -239,7 +239,6 @@ export function useModuleBasicSetting(tabNum) { toggleSelection(isExistSurface) }) } else { - let offsetLength = canvasSetting.roofSizeSet === '3' ? -30 : (trestleDetail.eaveIntvl / 10) * -1 setSurfaceShapePattern(roof, roofDisplay.column, true, roof.roofMaterial) //패턴 변경 // let offsetPoints = createPaddingPolygon(createRoofPolygon(roof.points), roof.lines).vertices //안쪽 offset let offsetPoints = null @@ -252,10 +251,16 @@ export function useModuleBasicSetting(tabNum) { //margin polygon 의 point가 기준 polygon의 밖에 있는지 판단한다. const allPointsOutside = result.every((point) => !originPolygon.inPolygon(point)) - if (allPointsOutside) { - offsetPoints = createMarginPolygon(polygon, roof.lines).vertices + if (canvasSetting.roofSizeSet == '3') { + //육지붕일때는 그냥 하드코딩 + offsetPoints = offsetPolygon(roof.points, -30) //육지붕일때 } else { - offsetPoints = createPaddingPolygon(polygon, roof.lines).vertices + //육지붕이 아닐때 + if (allPointsOutside) { + offsetPoints = createMarginPolygon(polygon, roof.lines).vertices + } else { + offsetPoints = createPaddingPolygon(polygon, roof.lines).vertices + } } //모듈설치영역?? 생성 @@ -263,7 +268,7 @@ export function useModuleBasicSetting(tabNum) { const surfaceId = uuidv4() let isNorth = false - if (canvasSetting.roofSizeSet !== '3') { + if (canvasSetting.roofSizeSet != '3') { //북면이 있지만 if (roof.directionText && roof.directionText.indexOf('北') > -1) { //북쪽일때 해당 서북서, 동북동은 제외한다고 한다 @@ -2895,8 +2900,13 @@ export function useModuleBasicSetting(tabNum) { targetRoof.angle = -angle targetSurface.angle = -angle + const newLines = createLinesFromPolygon(targetSurface.getCurrentPoints()) + targetSurface.set({ lines: newLines }) + targetRoof.fire('modified') targetSurface.fire('modified') + targetRoof.setCoords() + targetSurface.setCoords() moduleSetupSurfaces.push(targetSurface) } canvas.remove(obj) @@ -2990,37 +3000,92 @@ export function useModuleBasicSetting(tabNum) { let moduleGroup = [] - const flatRoofDownFlowSetupModule = (surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, marginWidth, marginHeight) => { - checkedModule.forEach((module, index) => { - const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) + const flatRoofDownFlowSetupModule = ( + surfaceMaxLines, + maxLengthLine, + moduleSetupArray, + moduleSetupSurface, + intvHor, + intvVer, + containsBatchObjects, + ) => { + let setupModule = [] - const flowLines = getFlowLines(moduleSetupSurface, height) + let installedLastHeightCoord = 0 //마지막으로 설치된 모듈의 좌표 + let installedModuleHeightCount = 0 //마지막으로 설치된 모듈의 카운트 + let flowLines - let startPoint = flowLines.bottom + checkedModule.forEach((module, moduleIndex) => { + //모듈의 넓이 높이를 가져옴 (복시도 촌수 적용) + //1번 깔았던 모듈 기준으로 잡야아함 + let { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) - const maxLeftEndPoint = surfaceMaxLines.left.x1 //최 좌측 - const maxRightEndPoint = surfaceMaxLines.right.x1 //최 우측 - const maxTopEndPoint = surfaceMaxLines.top.y1 //최 상단 + if (moduleIndex === 0) { + flowLines = getFlowLines(moduleSetupSurface, height) + if (flowLines.bottom.type === 'curve') { + flowLines = getFlowLines(moduleSetupSurface, width) + } + } - let totalLeftEndPoint = maxLeftEndPoint - startPoint.x1 - let totalTopEndPoint = maxTopEndPoint - startPoint.y1 - let totalWidth = Math.ceil(Math.abs(maxRightEndPoint - maxLeftEndPoint) / width) - let diffLeftEndPoint = Math.abs(totalLeftEndPoint / width) - let diffTopEndPoint = Math.abs(totalTopEndPoint / height) - let startColPoint = Math.abs(width * Math.ceil(diffLeftEndPoint) - startPoint.x1) - let tempMaxWidth = width //최대배치인지 확인하려고 넣음 + //육지붕이 아닐때만 넣는다 육지붕일땐 클릭 이벤트에 별도로 넣어놓음 + const moduleArray = [] - for (let j = 0; j < diffTopEndPoint; j++) { - bottomMargin = marginHeight * j - for (let i = 0; i <= totalWidth; i++) { - leftMargin = marginWidth * i + let calcAreaWidth = flowLines.right.x1 - flowLines.left.x1 //오른쪽 x에서 왼쪽 x를 뺀 가운데를 찾는 로직 + let calcModuleWidthCount = calcAreaWidth / (width + intvHor) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 + let calcMaxModuleWidthCount = calcModuleWidthCount //최대 모듈 단수가 있기 때문에 최대 단수보다 카운트가 크면 최대 단수로 씀씀 + let totalModuleWidthCount = Math.floor(calcMaxModuleWidthCount) //치조배치일경우는 한개 더 넣는다 - square = [ - [startColPoint + tempMaxWidth * i + leftMargin, startPoint.y1 - height * j - bottomMargin], - [startColPoint + tempMaxWidth * i + width + leftMargin, startPoint.y1 - height * j - bottomMargin], - [startColPoint + tempMaxWidth * i + width + leftMargin, startPoint.y1 - height * j - height - bottomMargin], - [startColPoint + tempMaxWidth * i + leftMargin, startPoint.y1 - height * j - height - bottomMargin], - [startColPoint + tempMaxWidth * i + leftMargin, startPoint.y1 - height * j - bottomMargin], + let calcAreaheight = flowLines.bottom.y1 - flowLines.top.y1 //오른쪽 y에서 왼쪽 y를 뺀 가운데를 찾는 로직 + let calcModuleHeightCount = calcAreaheight / (height + intvVer) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 + let calcMaxModuleHeightCount = calcModuleHeightCount //최대 모듈 단수가 있기 때문에 최대 단수보다 카운트가 크면 최대 단수로 씀씀 + let totalModuleHeightCount = Math.floor(calcMaxModuleHeightCount) //치조배치일경우는 한개 더 넣는다 + + let calcStartPoint = flowLines.right.type === 'flat' ? (calcAreaWidth - totalModuleWidthCount * width) / 2 : 0 //반씩 나눠서 중앙에 맞춤 bottom 기준으로 양변이 직선일때만 가운데 정렬 + let startPointX = flowLines.left.x1 + calcStartPoint //시작점을 만든다 + + //근데 양변이 곡선이면 중앙에 맞추기 위해 아래와 위의 길이를 재서 모듈의 길이를 나눠서 들어갈수 있는 갯수가 동일하면 가운데로 정렬 시킨다 + if (flowLines.left.type === 'curve' && flowLines.right.type === 'curve') { + startPointX = flowLines.left.x1 + (calcAreaWidth - totalModuleWidthCount * width) / 2 + + if (flowLines.left.x1 < flowLines.bottom.x1) { + startPointX = flowLines.left.x1 + } + } + + let heightMargin = 0 + let widthMargin = 0 + let chidoriLength = 0 + let moduleMaxRows = totalModuleHeightCount + + //첫번재 모듈 설치 후 두번째 모듈을 몇개까지 설치 할 수 있는지 계산 + if (moduleIndex > 0) { + moduleMaxRows = moduleMaxRows - installedModuleHeightCount //두번째 모듈일때 + } + + let isInstall = false + + for (let i = 0; i < moduleMaxRows; i++) { + let moduleY = flowLines.bottom.y1 - height * i - 1 //살짝 여유를 준다 + + //두번째 모듈 -> 혼합일 경우의 설치될 모듈 높이를 계산 + if (moduleIndex > 0) { + moduleY = installedLastHeightCoord - intvVer + } + + //첫번째는 붙여서 두번째는 마진을 주고 설치 + heightMargin = i === 0 ? 0 : intvVer * i + + for (let j = 0; j < totalModuleWidthCount; j++) { + let moduleX = startPointX + width * j + 1 //5정도 마진을 준다 + widthMargin = j === 0 ? 0 : intvHor * j // 가로 마진값 + chidoriLength = 0 //치도리가 아니여도 기본값을 5정도 준다 + + let square = [ + [moduleX + widthMargin, moduleY - height - heightMargin], + [moduleX + widthMargin, moduleY - heightMargin], + [moduleX + width + widthMargin, moduleY - heightMargin], + [moduleX + width + widthMargin, moduleY - height - heightMargin], + [moduleX + widthMargin, moduleY - height - heightMargin], ] let squarePolygon = turf.polygon([square]) @@ -3029,15 +3094,47 @@ export function useModuleBasicSetting(tabNum) { moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id, moduleInfo: module } let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) - canvas?.add(tempModule) - moduleSetupArray.push(tempModule) - moduleGroup.push(tempModule) + + let disjointFromTrestle = checkModuleDisjointSurface(squarePolygon, polygonToTurfPolygon(moduleSetupSurface, true)) + let isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) + + if (disjointFromTrestle && isDisjoint) { + //최초 한번은 그냥 그린다 + //겹치는지 확인해서 포함된 모듈만 그린다 + canvas?.add(tempModule) + moduleSetupArray.push(tempModule) + moduleArray.push(tempModule) + canvas.renderAll() + + // ++installedModuleHeightCount + + isInstall = true + //마지막에 설치된 모듈의 Y 좌표 + installedLastHeightCoord = moduleY - height - heightMargin + } else { + //디버깅용 + // tempModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) + // canvas?.add(tempModule) + // canvas.renderAll() + } + } + if (isInstall) { + ++installedModuleHeightCount } } + setupModule.push(moduleArray) }) } - const flatRoofLeftFlowSetupModule = (surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, marginWidth, marginHeight) => { + const flatRoofLeftFlowSetupModule = ( + surfaceMaxLines, + maxLengthLine, + moduleSetupArray, + moduleSetupSurface, + intvHor, + intvVer, + containsBatchObjects, + ) => { checkedModule.forEach((module, index) => { const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) const flowLines = getFlowLines(moduleSetupSurface, width) @@ -3082,7 +3179,15 @@ export function useModuleBasicSetting(tabNum) { }) } - const flatRoofTopFlowSetupModule = (surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, marginWidth, marginHeight) => { + const flatRoofTopFlowSetupModule = ( + surfaceMaxLines, + maxLengthLine, + moduleSetupArray, + moduleSetupSurface, + intvHor, + intvVer, + containsBatchObjects, + ) => { checkedModule.forEach((module, index) => { const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) const flowLines = getFlowLines(moduleSetupSurface, height) @@ -3129,7 +3234,15 @@ export function useModuleBasicSetting(tabNum) { }) } - const flatRoofRightFlowSetupModule = (surfaceMaxLines, moduleSetupArray, moduleSetupSurface, marginWidth, marginHeight) => { + const flatRoofRightFlowSetupModule = ( + surfaceMaxLines, + maxLengthLine, + moduleSetupArray, + moduleSetupSurface, + intvHor, + intvVer, + containsBatchObjects, + ) => { checkedModule.forEach((module, index) => { const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) const flowLines = getFlowLines(moduleSetupSurface, width) @@ -3186,20 +3299,13 @@ export function useModuleBasicSetting(tabNum) { const containsBatchObjects = objectsIncludeSurface(turfModuleSetupSurface) //배치면에 오브젝트(도머, 개구등)이 있는지 확인하는 로직 const surfaceMaxLines = findSetupSurfaceMaxLines(moduleSetupSurface) - const marginWidth = 1 - const marginHeight = 3 + const intvHor = 30 + const intvVer = 10 canvas.renderAll() - if (compasDeg >= 0 && compasDeg < 90) { - flatRoofDownFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, marginWidth, marginHeight) - } else if (compasDeg >= 90 && compasDeg < 180) { - flatRoofLeftFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, marginWidth, marginHeight) - } else if (compasDeg >= 180 && compasDeg < 270) { - flatRoofRightFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, marginWidth, marginHeight) - } else { - flatRoofTopFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, marginWidth, marginHeight) - } + //육지붕은 왼쪽 기준으로 그려진다 + flatRoofDownFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, intvHor, intvVer, containsBatchObjects) const setupedModules = moduleSetupArray.filter((module, index) => { let disjointFromTrestle = checkModuleDisjointSurface(module.turfPoints, turfModuleSetupSurface) diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 557342b8..348f1291 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -3536,3 +3536,18 @@ export const calcLineActualSize = (points, degree) => { } return Big(planeSize).pow(2).plus(height.pow(2)).sqrt().abs().round().toNumber() } + +export const createLinesFromPolygon = (points) => { + const lines = [] + for (let i = 0; i < points.length; i++) { + const nextIndex = (i + 1) % points.length + const line = new fabric.Line([points[i].x, points[i].y, points[nextIndex].x, points[nextIndex].y], { + stroke: 'red', + strokeWidth: 2, + selectable: false, + evented: false, + }) + lines.push(line) + } + return lines +}