From 2f54da76c1c2579bebf884c11a4e69a6f3d3f62b Mon Sep 17 00:00:00 2001 From: yjnoh Date: Thu, 20 Feb 2025 16:50:38 +0900 Subject: [PATCH] =?UTF-8?q?=EB=AA=A8=EB=93=88=20=EB=B0=B0=EC=B9=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/2025-02-13_Qcell_회의.txt | 36 + docs/2025-02-14_Qcell_회의.txt | 10 + .../common/context-menu/QContextMenu.jsx | 2 +- src/hooks/common/useCommonUtils.js | 2 +- src/hooks/module/useModuleBasicSetting.js | 1362 +++++++++++++---- 5 files changed, 1076 insertions(+), 336 deletions(-) create mode 100644 docs/2025-02-13_Qcell_회의.txt create mode 100644 docs/2025-02-14_Qcell_회의.txt diff --git a/docs/2025-02-13_Qcell_회의.txt b/docs/2025-02-13_Qcell_회의.txt new file mode 100644 index 00000000..3aa60619 --- /dev/null +++ b/docs/2025-02-13_Qcell_회의.txt @@ -0,0 +1,36 @@ +1. 회로할당 -> + 수동 할당시 와트수 소수점 노출 + +2. 모듈 -> + 멀티 모듈일시 모듈 순번에 따라 배치면 그리기 적용해야됨 + 멀티 모듈시 모듈 간격 붙여서 조정 + +3. contextMenu -> + 한번 클릭 후 contextMenu 호출 재호출시 화면에 안나옴 + +4. 수치 입력시 -> + 반각?전각? 입력 처리 필요???????????????? + +5. 지도 호출 -> + 최초 호출 후 삭제, 재호출 안됨 + +6. 도면 화면 -> + redo, undo 제거 + +7. 모든 배치면 -> + 배치면 외각선 굵기 조절 + +8. 패브릭 캔버스 -> + 줌, 확대 기능 선택 오류 수정 필요 + +9. 모듈선택 -> + 모듈 선택 페이지 단계 변경 예정정(현업 화면에 너무 크게 적용) + +10. 외벽선 삭제시 수치 삭제 처리 필요 + +11. 모듈 삭제 후 재 설치시 모듈이 겹친다고 오류남 + +12. 모듈 수동시 첫번째는 아무데나 놓을 수 있고 두번째 부터는 무조건 주변에 모듈이 있어야 한다는 조건이 있어야 한다고 함 + +13. 견적서 다운로드 이미지 정비율이 아님 + diff --git a/docs/2025-02-14_Qcell_회의.txt b/docs/2025-02-14_Qcell_회의.txt new file mode 100644 index 00000000..5add84f4 --- /dev/null +++ b/docs/2025-02-14_Qcell_회의.txt @@ -0,0 +1,10 @@ +1. 오픈 예정일정 -> 신상품 7월에 오픈 그와 같이 하는게 어떻냐? + +2. 웹 상에서 단축키 모드 추가 + +3. 형이동 동선이동 작업 해보겠다. + +4. 모듈 작업 확정 (좌하, 우상) + +5. 발전 시뮬레이션 qsp에 이관 작업(유지보수) + diff --git a/src/components/common/context-menu/QContextMenu.jsx b/src/components/common/context-menu/QContextMenu.jsx index 63160eda..955a3e4b 100644 --- a/src/components/common/context-menu/QContextMenu.jsx +++ b/src/components/common/context-menu/QContextMenu.jsx @@ -40,7 +40,7 @@ export default function QContextMenu(props) { if (!contextRef.current) return const handleContextMenu = (e) => { - // e.preventDefault() //기존 contextmenu 막고 + e.preventDefault() //기존 contextmenu 막고 if (tempGridMode) return const position = { x: window.innerWidth / 2 < e.pageX ? e.pageX - 240 : e.pageX, diff --git a/src/hooks/common/useCommonUtils.js b/src/hooks/common/useCommonUtils.js index 60bbb9ec..da5d558d 100644 --- a/src/hooks/common/useCommonUtils.js +++ b/src/hooks/common/useCommonUtils.js @@ -591,8 +591,8 @@ export function useCommonUtils() { //배치면일 경우 if (obj.name === 'roof') { clonedObj.setCoords() + clonedObj.set({ direction: obj.direction, directionText: obj.directionText, roofMaterial: obj.roofMaterial }) clonedObj.fire('polygonMoved') - clonedObj.set({ direction: obj.direction, directionText: obj.directionText }) canvas.renderAll() addLengthText(clonedObj) //수치 추가 drawDirectionArrow(clonedObj) //방향 화살표 추가 diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index 74158c1f..3c27393b 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -448,7 +448,7 @@ export function useModuleBasicSetting(tabNum) { let tmpHeight = flowDirection === 'south' || flowDirection === 'north' ? moduleHeight : moduleWidth let { width, height } = - canvasSetting.roofSizeSet === '1' + canvasSetting.roofSizeSet == '1' ? calculateVisibleModuleHeight(tmpWidth, tmpHeight, getDegreeByChon(moduleSetupSurfaces[i].roofMaterial.pitch), flowDirection) : { width: tmpWidth, height: tmpHeight } @@ -568,14 +568,14 @@ export function useModuleBasicSetting(tabNum) { 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 - holdCellCenterY) < cellSnapDistance) { + tempModule.top = holdCellCenterY + } + //아랫쪽 -> 가운데 + if (Math.abs(smallBottom - holdCellCenterY) < cellSnapDistance) { + tempModule.top = holdCellCenterY - height + } }) } @@ -842,6 +842,7 @@ export function useModuleBasicSetting(tabNum) { return turf.booleanContains(turfModuleSetupSurface, squarePolygon) || turf.booleanWithin(squarePolygon, turfModuleSetupSurface) } + //흐름 방향이 남쪽(아래) const downFlowSetupModule = ( surfaceMaxLines, maxLengthLine, @@ -854,67 +855,133 @@ export function useModuleBasicSetting(tabNum) { ) => { let setupModule = [] - checkedModule.forEach((module, index) => { - const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) + const trestleDetailData = moduleSetupSurface.trestleDetail + const moduleMaxCols = trestleDetailData.moduleMaxCols // 모듈 최대 가로 설치 갯수 - const flowLines = getFlowLines(moduleSetupSurface, height) - //육지붕이 아닐때만 넣는다 육지붕일땐 클릭 이벤트에 별도로 넣어놓음 - // let startPoint = flowLines.bottom + let installedLastHeightCoord = 0 //마지막으로 설치된 모듈의 좌표 + let installedModuleHeightCount = 0 //마지막으로 설치된 모듈의 카운트 + let isChidoriLine = false + let flowLines - let startPoint = flowLines.bottom - const moduleArray = [] + checkedModule.forEach((module, moduleIndex) => { + const tmpModuleData = trestleDetailData.module.filter((moduleObj) => module.moduleTpCd === moduleObj.moduleTpCd)[0] + //혼합모듈일때는 mixModuleMaxRows 값이 0 이상임 + let moduleMaxRows = tmpModuleData.mixModuleMaxRows === 0 ? tmpModuleData.moduleMaxRows : tmpModuleData.mixModuleMaxRows - console.log('flowLines', flowLines) + // 혼합모듈 포함 총 모듈 설치 높이 갯수 + const totalModuleMaxRows = tmpModuleData.moduleMaxRows - if (isCenter) { - //중앙배치일 경우에는 계산한다 - if (flowLines.bottom.type === 'flat' && flowLines.left.type === 'flat' && flowLines.right.type === 'flat') { - //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 - const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 - const halfModuleWidthLength = width / 2 - startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } + //모듈의 넓이 높이를 가져옴 (복시도 촌수 적용) + //1번 깔았던 모듈 기준으로 잡야아함 + let { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) - if (flowLines.top.type === 'flat') { - //상단까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 - const heightLength = Math.abs(flowLines.left.y1 - flowLines.left.y2) //옆에에 길이에서 반을 가른다 - const heightMargin = Math.abs(heightLength - height * Math.floor(heightLength / height)) / 2 - startPoint = { ...startPoint, y1: startPoint.y1 - heightMargin } - } + if (moduleIndex === 0) { + flowLines = getFlowLines(moduleSetupSurface, height) + if (flowLines.bottom.type === 'curve') { + flowLines = getFlowLines(moduleSetupSurface, width) } } + + //육지붕이 아닐때만 넣는다 육지붕일땐 클릭 이벤트에 별도로 넣어놓음 + // let startPoint = flowLines.bottom + const moduleArray = [] + // const moduleMaxRows = module + //밑에가 곡선이면 모듈의 넓이를 가지고 계산한다 + // if (isCenter) { + // //중앙배치일 경우에는 계산한다 + // if (flowLines.bottom.type === 'flat' && flowLines.left.type === 'flat' && flowLines.right.type === 'flat') { + // //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 + // const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 + // const halfModuleWidthLength = width / 2 + // startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } + + // if (flowLines.top.type === 'flat') { + // //상단까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 + // const heightLength = Math.abs(flowLines.left.y1 - flowLines.left.y2) //옆에에 길이에서 반을 가른다 + // const heightMargin = Math.abs(heightLength - height * Math.floor(heightLength / height)) / 2 + // startPoint = { ...startPoint, y1: startPoint.y1 - heightMargin } + // } + // } + // } //밑에가 평면이면 좌측으로 붙여서 배치 // if (flowLines.bottom.type === 'flat' && flowLines.left.type === 'curve') { // startPoint = flowLines.left // } - const maxLeftEndPoint = surfaceMaxLines.left.x1 //최 좌측 - const maxRightEndPoint = surfaceMaxLines.right.x1 //최 우측 - const maxTopEndPoint = surfaceMaxLines.top.y1 //최 상단 + // let leftEnd = new fabric.Circle({ left: surfaceMaxLines.left.x1 - 2.5, top: surfaceMaxLines.left.y1 - 2.5, radius: 5, fill: 'green' }) + // let rightEnd = new fabric.Circle({ left: surfaceMaxLines.right.x1 - 2.5, top: surfaceMaxLines.right.y1 - 2.5, radius: 5, fill: 'green' }) + // let topEnd = new fabric.Circle({ left: surfaceMaxLines.top.x1 - 2.5, top: surfaceMaxLines.top.y1 - 2.5, radius: 5, fill: 'green' }) - 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 = isMaxSetup ? width / 2 : width //최대배치인지 확인하려고 넣음 - if (isMaxSetup) totalWidth = totalWidth * 2 //최대배치시 2배로 늘려서 반씩 검사하기위함 + // canvas?.add(leftEnd) + // canvas?.add(rightEnd) + // canvas?.add(topEnd) - for (let j = 0; j < diffTopEndPoint; j++) { - bottomMargin = j === 0 ? 0 : intvVer * j - for (let i = 0; i <= totalWidth; i++) { - leftMargin = i === 0 ? 0 : intvHor * i - chidoriLength = 0 + // canvas.renderAll() + + let calcAreaWidth = flowLines.right.x1 - flowLines.left.x1 //오른쪽 x에서 왼쪽 x를 뺀 가운데를 찾는 로직 + let calcModuleWidthCount = calcAreaWidth / (width + intvHor) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 + let calcMaxModuleWidthCount = calcModuleWidthCount > moduleMaxCols ? moduleMaxCols : calcModuleWidthCount //최대 모듈 단수가 있기 때문에 최대 단수보다 카운트가 크면 최대 단수로 씀씀 + // let totalModuleWidthCount = isChidori ? Math.abs(calcMaxModuleWidthCount) : Math.floor(calcMaxModuleWidthCount) //치조배치일경우는 한개 더 넣는다 + let totalModuleWidthCount = Math.floor(calcMaxModuleWidthCount) //치조배치일경우는 한개 더 넣는다 + + // let calcAreaHeight = flowLines.bottom.y1 - flowLines.top.y1 + // let calcModuleHeightCount = calcAreaHeight / (height + intvVer) + + 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 + } + + let heightMargin = 0 + let widthMargin = 0 + let chidoriLength = 0 + + //첫번재 모듈 설치 후 두번째 모듈을 몇개까지 설치 할 수 있는지 계산 + if (moduleIndex > 0) { + moduleMaxRows = totalModuleMaxRows - installedModuleHeightCount //두번째 모듈일때 + isChidoriLine = installedModuleHeightCount % 2 != 0 ? true : false //첫번째에서 짝수에서 끝났으면 홀수는 치도리가 아님 짝수는 치도리 + } + + let isInstall = false + + for (let i = 0; i < moduleMaxRows; i++) { + let moduleY = flowLines.bottom.y1 - height * i - 0.1 //살짝 여유를 준다 + + //두번째 모듈 -> 혼합일 경우의 설치될 모듈 높이를 계산 + if (moduleIndex > 0) { + moduleY = installedLastHeightCoord - intvVer + } + + //전체 설치 간으 모듈이랑 같으면 반복을 멈춘다 + if (totalModuleMaxRows === installedModuleHeightCount) { + break + } + + //첫번째는 붙여서 두번째는 마진을 주고 설치 + heightMargin = i === 0 ? 0 : intvVer * i + + for (let j = 0; j < totalModuleWidthCount; j++) { + let moduleX = startPointX + width * j + 0.1 //5정도 마진을 준다 + widthMargin = j === 0 ? 0 : intvHor * j // 가로 마진값 + chidoriLength = 0 //치도리가 아니여도 기본값을 5정도 준다 if (isChidori && !isMaxSetup) { - chidoriLength = j % 2 === 0 ? 0 : width / 2 - intvHor + chidoriLength = installedModuleHeightCount % 2 == 0 ? 0 : width / 2 - intvHor } - square = [ - [startColPoint + tempMaxWidth * i - chidoriLength + leftMargin, startPoint.y1 - height * j - bottomMargin], - [startColPoint + tempMaxWidth * i + width - chidoriLength + leftMargin, startPoint.y1 - height * j - bottomMargin], - [startColPoint + tempMaxWidth * i + width - chidoriLength + leftMargin, startPoint.y1 - height * j - height - bottomMargin], - [startColPoint + tempMaxWidth * i - chidoriLength + leftMargin, startPoint.y1 - height * j - height - bottomMargin], - [startColPoint + tempMaxWidth * i - chidoriLength + leftMargin, startPoint.y1 - height * j - bottomMargin], + //치도리 일때 는 짝수(1 기준) 일때만 치도리 라인으로 본다 + if (isChidori && isChidoriLine) { + chidoriLength = width / 2 - intvHor + } + + let square = [ + [moduleX + widthMargin + chidoriLength, moduleY - height - heightMargin], + [moduleX + widthMargin + chidoriLength, moduleY - heightMargin], + [moduleX + width + widthMargin + chidoriLength, moduleY - heightMargin], + [moduleX + width + widthMargin + chidoriLength, moduleY - height - heightMargin], + [moduleX + widthMargin + chidoriLength, moduleY - height - heightMargin], ] let squarePolygon = turf.polygon([square]) @@ -928,148 +995,114 @@ export function useModuleBasicSetting(tabNum) { let isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) if (disjointFromTrestle && isDisjoint) { - if (index > 0) { - setupModule.forEach((item) => { - const isOverlap = item.some((item2) => turf.booleanOverlap(squarePolygon, polygonToTurfPolygon(item2, true))) - if (!isOverlap) { - canvas?.add(tempModule) - moduleSetupArray.push(tempModule) - moduleArray.push(tempModule) - canvas.renderAll() - } - }) - } else { - //최초 한번은 그냥 그린다 - //겹치는지 확인해서 포함된 모듈만 그린다 - canvas?.add(tempModule) - moduleSetupArray.push(tempModule) - moduleArray.push(tempModule) - canvas.renderAll() - } + //최초 한번은 그냥 그린다 + //겹치는지 확인해서 포함된 모듈만 그린다 + canvas?.add(tempModule) + moduleSetupArray.push(tempModule) + moduleArray.push(tempModule) + canvas.renderAll() + + // ++installedModuleHeightCount + + isInstall = true + //마지막에 설치된 모듈의 Y 좌표 + installedLastHeightCoord = moduleY - height - heightMargin + + // if (j === 0) { + // let startCircle = new fabric.Rect({ + // left: surfaceMaxLines.left.x1, + // top: installedLastHeightCoord, + // stroke: 'red', + // strokeWidth: 1, + // width: 5, + // height: 5, + // fill: 'red', + // originX: 'center', + // originY: 'center', + // }) + // canvas.add(startCircle) + // } } else { //디버깅용 - // tempModule.set({ fill: 'rgba(255,190,41, 0.4)', stroke: 'black', strokeWidth: 1 }) + // tempModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) // canvas?.add(tempModule) // canvas.renderAll() } } + if (isInstall) { + ++installedModuleHeightCount + } } + // } + // else { + // //밑바닥이 직선이 아닐때 + // //모양이 이상할때 - setupModule.push(moduleArray) - }) - } + // 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 = isMaxSetup ? width / 2 : width //최대배치인지 확인하려고 넣음 + // if (isMaxSetup) totalWidth = totalWidth * 2 //최대배치시 2배로 늘려서 반씩 검사하기위함 - const leftFlowSetupModule = ( - surfaceMaxLines, - maxLengthLine, - moduleSetupArray, - moduleSetupSurface, - containsBatchObjects, - isCenter = false, - intvHor, - intvVer, - ) => { - let setupModule = [] + // for (let j = 0; j < diffTopEndPoint; j++) { + // bottomMargin = j === 0 ? 0 : intvVer * j + // for (let i = 0; i <= totalWidth; i++) { + // leftMargin = i === 0 ? 0 : intvHor * i + // chidoriLength = 0 + // if (isChidori && !isMaxSetup) { + // chidoriLength = j % 2 === 0 ? 0 : width / 2 - intvHor + // } - checkedModule.forEach((module, index) => { - const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) - let flowLines = getFlowLines(moduleSetupSurface, width) - //육지붕이 아닐때만 넣는다 육지붕일땐 클릭 이벤트에 별도로 넣어놓음 - let startPoint = flowLines.left - const moduleArray = [] + // square = [ + // [startColPoint + tempMaxWidth * i - chidoriLength + leftMargin, startPoint.y1 - height * j - bottomMargin], + // [startColPoint + tempMaxWidth * i + width - chidoriLength + leftMargin, startPoint.y1 - height * j - bottomMargin], + // [startColPoint + tempMaxWidth * i + width - chidoriLength + leftMargin, startPoint.y1 - height * j - height - bottomMargin], + // [startColPoint + tempMaxWidth * i - chidoriLength + leftMargin, startPoint.y1 - height * j - height - bottomMargin], + // [startColPoint + tempMaxWidth * i - chidoriLength + leftMargin, startPoint.y1 - height * j - bottomMargin], + // ] - // if (flowLines.left.type === 'flat') { - // const tempPoint = { ...flowLines.top } - // startPoint = { ...flowLines.top, x1: tempPoint.x2, x2: tempPoint.x1 } - // } else { - // flowLines = getFlowLines(moduleSetupSurface, height) - // const tempPoint = { ...flowLines.left } - // startPoint = { ...flowLines.left, x1: tempPoint.x1 + 5, x2: tempPoint.x2, y1: tempPoint.y1 - 5 } + // let squarePolygon = turf.polygon([square]) + // let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) + // let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) + + // 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 isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) + + // if (disjointFromTrestle && isDisjoint) { + // if (moduleIndex > 0) { + // setupModule.forEach((item) => { + // const isOverlap = item.some((item2) => turf.booleanOverlap(squarePolygon, polygonToTurfPolygon(item2, true))) + // if (!isOverlap) { + // canvas?.add(tempModule) + // moduleSetupArray.push(tempModule) + // moduleArray.push(tempModule) + // canvas.renderAll() + // } + // }) + // } else { + // //최초 한번은 그냥 그린다 + // //겹치는지 확인해서 포함된 모듈만 그린다 + // canvas?.add(tempModule) + // moduleSetupArray.push(tempModule) + // moduleArray.push(tempModule) + // canvas.renderAll() + // } + // } else { + // //디버깅용 + // tempModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) + // canvas?.add(tempModule) + // canvas.renderAll() + // } + // } + // } // } - //중앙배치일 경우에는 계산한다 - if (isCenter) { - if (flowLines.left.type === 'flat' && flowLines.bottom.type === 'flat' && flowLines.top.type === 'flat') { - //좌측 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 - const halfWidthLength = Math.abs(startPoint.y1 + startPoint.y2) / 2 //밑에 길이에서 반을 가른다 - const halfModuleWidthLength = height / 2 - startPoint = { ...startPoint, y1: halfWidthLength - halfModuleWidthLength } - if (flowLines.right.type === 'flat') { - //우측까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 - const widthLength = Math.abs(flowLines.top.x1 - flowLines.top.x2) //옆에에 길이에서 반을 가른다 - const widthMargin = Math.abs(widthLength - width * Math.floor(widthLength / width)) / 2 - startPoint = { ...startPoint, x1: startPoint.x1 + widthMargin } - } - } - } - - const maxRightEndPoint = surfaceMaxLines.right.x1 //최 우측 - const maxTopEndPoint = surfaceMaxLines.top.y1 //최 상단 - const maxBottomEndPoint = surfaceMaxLines.bottom.y1 //최하단 - - let totalTopEndPoint = Math.abs(maxTopEndPoint - startPoint.y1) //전체 높이에서 현재 높이를 뺌 - let diffTopEndPoint = Math.abs(totalTopEndPoint / height) - let totalHeight = Math.ceil(Math.abs(maxBottomEndPoint - maxTopEndPoint) / height) - let totalWidth = Math.abs(startPoint.x1 - maxRightEndPoint) / width - let startRowPoint = startPoint.y1 - height * Math.ceil(diffTopEndPoint) - - let tempMaxHeight = isMaxSetup ? height / 2 : height //최대배치인지 확인하려고 넣음 - if (isMaxSetup) totalHeight = totalHeight * 2 //최대배치시 2배로 늘려 서 반씩 검사 - - for (let i = 0; i <= totalWidth; i++) { - bottomMargin = i === 0 ? 0 : intvHor * i - for (let j = 0; j < totalHeight; j++) { - leftMargin = j === 0 ? 0 : intvVer * j - chidoriLength = 0 - if (isChidori && !isMaxSetup) { - chidoriLength = i % 2 === 0 ? 0 : height / 2 - } - - square = [ - [startPoint.x1 + width * i + bottomMargin, startRowPoint + tempMaxHeight * j + leftMargin - chidoriLength], - [startPoint.x1 + width * i + width + bottomMargin, startRowPoint + tempMaxHeight * j + leftMargin - chidoriLength], - [startPoint.x1 + width * i + width + bottomMargin, startRowPoint + tempMaxHeight * j + height + leftMargin - chidoriLength], - [startPoint.x1 + width * i + bottomMargin, startRowPoint + tempMaxHeight * j + height + leftMargin - chidoriLength], - [startPoint.x1 + width * i + bottomMargin, startRowPoint + tempMaxHeight * j + leftMargin - chidoriLength], - ] - - let squarePolygon = turf.polygon([square]) - let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) - let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) - - // if (disjointFromTrestle && isDisjoint) { - 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 isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) - - if (disjointFromTrestle && isDisjoint) { - if (index > 0) { - setupModule.forEach((item) => { - const isOverlap = item.some((item2) => turf.booleanOverlap(squarePolygon, polygonToTurfPolygon(item2, true))) - if (!isOverlap) { - canvas?.add(tempModule) - moduleSetupArray.push(tempModule) - moduleArray.push(tempModule) - canvas.renderAll() - } - }) - } else { - //최초 한번은 그냥 그린다 - //겹치는지 확인해서 포함된 모듈만 그린다 - canvas?.add(tempModule) - moduleSetupArray.push(tempModule) - moduleArray.push(tempModule) - canvas.renderAll() - } - } else { - //디버깅용 - // tempModule.set({ fill: 'rgba(255,190,41, 0.4)', stroke: 'black', strokeWidth: 1 }) - // canvas?.add(tempModule) - // canvas.renderAll() - } - } - } setupModule.push(moduleArray) }) } @@ -1086,81 +1119,136 @@ export function useModuleBasicSetting(tabNum) { ) => { let setupModule = [] - checkedModule.forEach((module, index) => { + const trestleDetailData = moduleSetupSurface.trestleDetail + const moduleMaxCols = trestleDetailData.moduleMaxCols // 모듈 최대 가로 설치 갯수 + + let installedLastHeightCoord = 0 //마지막으로 설치된 모듈의 좌표 + let installedModuleHeightCount = 0 //마지막으로 설치된 모듈의 카운트 + let isChidoriLine = false + let flowLines + + checkedModule.forEach((module, moduleIndex) => { + const tmpModuleData = trestleDetailData.module.filter((moduleObj) => module.moduleTpCd === moduleObj.moduleTpCd)[0] + //혼합모듈일때는 mixModuleMaxRows 값이 0 이상임 + let moduleMaxRows = tmpModuleData.mixModuleMaxRows === 0 ? tmpModuleData.moduleMaxRows : tmpModuleData.mixModuleMaxRows + // 혼합모듈 포함 총 모듈 설치 높이 갯수 + const totalModuleMaxRows = tmpModuleData.moduleMaxRows + const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) - const flowLines = getFlowLines(moduleSetupSurface, height) - let startPoint = flowLines.top - // if (flowLines.top.type === 'flat' && flowLines.right.type === 'curve') { - // startPoint = flowLines.right - // } - - const moduleArray = [] - - if (isCenter) { - //중앙배치일 경우에는 계산한다 - if (flowLines.top.type === 'flat' && flowLines.left.type === 'flat' && flowLines.right.type === 'flat') { - //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 - const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 - const halfModuleWidthLength = width / 2 - startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } - - if (flowLines.bottom.type === 'flat') { - //상단까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 - const heightLength = Math.abs(flowLines.left.y1 - flowLines.left.y2) //옆에에 길이에서 반을 가른다 - const heightMargin = Math.abs(heightLength - height * Math.floor(heightLength / height)) / 2 - startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength, y1: startPoint.y1 - heightMargin } - } + if (moduleIndex === 0) { + flowLines = getFlowLines(moduleSetupSurface, height) + if (flowLines.top.type === 'curve') { + flowLines = getFlowLines(moduleSetupSurface, width) } } - // else { - // //중앙배치가 아닐때도 흐름 방향 기준면으로 양면이 직선이면 가운데 배치 - // if (flowModuleLine.bottom.type === 'flat' && flowModuleLine.left.type === 'flat' && flowModuleLine.right.type === 'flat') { - // //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 - // const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 - // const halfModuleWidthLength = width / 2 - // startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } + + //흐름 방향이 북쪽(위) + + //육지붕이 아닐때만 넣는다 육지붕일땐 클릭 이벤트에 별도로 넣어놓음 + // let startPoint = flowLines.bottom + const moduleArray = [] + // const moduleMaxRows = module + + // if (isCenter) { + // //중앙배치일 경우에는 계산한다 + // if (flowLines.bottom.type === 'flat' && flowLines.left.type === 'flat' && flowLines.right.type === 'flat') { + // //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 + // const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 + // const halfModuleWidthLength = width / 2 + // startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } + + // if (flowLines.top.type === 'flat') { + // //상단까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 + // const heightLength = Math.abs(flowLines.left.y1 - flowLines.left.y2) //옆에에 길이에서 반을 가른다 + // const heightMargin = Math.abs(heightLength - height * Math.floor(heightLength / height)) / 2 + // startPoint = { ...startPoint, y1: startPoint.y1 - heightMargin } + // } + // } // } + //밑에가 평면이면 좌측으로 붙여서 배치 + // if (flowLines.bottom.type === 'flat' && flowLines.left.type === 'curve') { + // startPoint = flowLines.left // } - const maxLeftEndPoint = surfaceMaxLines.left.x1 //최 좌측 - const maxRightEndPoint = surfaceMaxLines.right.x1 //최 우측 - const maxBottomEndPoint = surfaceMaxLines.bottom.y1 //최하단 + // let leftEnd = new fabric.Circle({ left: surfaceMaxLines.left.x1 - 2.5, top: surfaceMaxLines.left.y1 - 2.5, radius: 5, fill: 'green' }) + // let rightEnd = new fabric.Circle({ left: surfaceMaxLines.right.x1 - 2.5, top: surfaceMaxLines.right.y1 - 2.5, radius: 5, fill: 'green' }) + // let bottomEnd = new fabric.Circle({ left: surfaceMaxLines.bottom.x1 - 2.5, top: surfaceMaxLines.bottom.y1 - 2.5, radius: 5, fill: 'green' }) - let totalLeftEndPoint = maxLeftEndPoint - startPoint.x1 - let totalRightEndPoint = maxLeftEndPoint - maxRightEndPoint - let totalBottomEndPoint = maxBottomEndPoint - startPoint.y1 - let diffLeftEndPoint = Math.abs(totalLeftEndPoint / width) - let diffRightEndPoint = Math.ceil(Math.abs(totalRightEndPoint / width)) - let diffBottomEndPoint = Math.ceil(Math.abs(totalBottomEndPoint / height)) - let startColPoint = Math.abs(width * Math.ceil(diffLeftEndPoint) - startPoint.x1) - let tempMaxWidth = isMaxSetup ? width / 2 : width //최대배치인지 확인하려고 넣음 - if (isMaxSetup) diffRightEndPoint = diffRightEndPoint * 2 //최대배치시 2배로 늘려서 반씩 검사하기위함 + // canvas?.add(leftEnd) + // canvas?.add(rightEnd) + // canvas?.add(bottomEnd) - startColPoint = Math.round(startColPoint - intvHor * diffRightEndPoint) + // canvas.renderAll() - for (let j = 0; j < diffBottomEndPoint; j++) { - bottomMargin = j === 0 ? 0 : intvVer * j - for (let i = 0; i < diffRightEndPoint; i++) { - leftMargin = i === 0 ? 0 : intvHor * i + let calcAreaWidth = flowLines.right.x1 - flowLines.left.x1 //오른쪽 x에서 왼쪽 x를 뺀 가운데를 찾는 로직 + let calcModuleWidthCount = calcAreaWidth / (width + intvHor) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 + let calcMaxModuleWidthCount = calcModuleWidthCount > moduleMaxCols ? moduleMaxCols : calcModuleWidthCount //최대 모듈 단수가 있기 때문에 최대 단수보다 카운트가 크면 최대 단수로 씀씀 + // let totalModuleWidthCount = isChidori ? Math.abs(calcMaxModuleWidthCount) : Math.floor(calcMaxModuleWidthCount) //치조배치일경우는 한개 더 넣는다 //??어쩔때는 붙고 어쩔때는 안붙고 멋대로??? + let totalModuleWidthCount = Math.floor(calcMaxModuleWidthCount) //치조배치일경우는 한개 더 넣는다 + + let calcStartPoint = flowLines.left.type === 'flat' ? (calcAreaWidth - totalModuleWidthCount * width) / 2 : 0 //반씩 나눠서 중앙에 맞춤 bottom 기준으로 양변이 직선일때만 가운데 정렬 + let startPointX = flowLines.right.x1 - calcStartPoint //시작점을 만든다 + + //근데 양변이 곡선이면 중앙에 맞추기 위해 아래와 위의 길이를 재서 모듈의 길이를 나눠서 들어갈수 있는 갯수가 동일하면 가운데로 정렬 시킨다 + if (flowLines.left.type === 'curve' && flowLines.right.type === 'curve') { + // const calcTopWidth = Math.abs(flowLines.top.x1 - flowLines.top.x2) + // const calcTopModuleWidthCount = calcTopWidth / (width + intvHor) + + // if (Math.floor(calcMaxModuleWidthCount) === Math.floor(calcTopModuleWidthCount)) { + startPointX = flowLines.right.x1 - (calcAreaWidth - totalModuleWidthCount * width) / 2 + // } + } + + let heightMargin = 0 + let widthMargin = 0 + let chidoriLength = 0 + + if (moduleIndex > 0) { + moduleMaxRows = totalModuleMaxRows - installedModuleHeightCount //두번째 모듈일때 + isChidoriLine = installedModuleHeightCount % 2 != 0 ? true : false //첫번째에서 짝수에서 끝났으면 홀수는 치도리가 아님 짝수는 치도리 + } + + let isInstall = false + + for (let i = 0; i < moduleMaxRows; i++) { + let moduleY = flowLines.top.y1 + height * i //탑의 y점에서부터 아래로 그려 내려간다 + + if (moduleIndex > 0) { + moduleY = installedLastHeightCoord + intvVer + 1 + } + + //전체 설치 간으 모듈이랑 같으면 반복을 멈춘다 + if (totalModuleMaxRows === installedModuleHeightCount) { + break + } + + heightMargin = i === 0 ? 0 : intvVer * i //모듈간에 마진이 있어 마진값도 넣음 + for (let j = 0; j < totalModuleWidthCount; j++) { + //모듈 열수 만큼 반복 + let moduleX = startPointX - width * j - 1 //시작점에서 우 -> 좌로 그려 내려간다 + widthMargin = j === 0 ? 0 : intvHor * j chidoriLength = 0 if (isChidori && !isMaxSetup) { - chidoriLength = j % 2 === 0 ? 0 : width / 2 - intvHor + chidoriLength = installedModuleHeightCount % 2 == 0 ? 0 : width / 2 - intvHor } - square = [ - [startColPoint + tempMaxWidth * i + chidoriLength + leftMargin, startPoint.y1 + height * j + bottomMargin], - [startColPoint + tempMaxWidth * i + chidoriLength + leftMargin, startPoint.y1 + height * j + height + bottomMargin], - [startColPoint + tempMaxWidth * i + width + chidoriLength + leftMargin, startPoint.y1 + height * j + height + bottomMargin], - [startColPoint + tempMaxWidth * i + width + chidoriLength + leftMargin, startPoint.y1 + height * j + bottomMargin], - [startColPoint + tempMaxWidth * i + chidoriLength + leftMargin, startPoint.y1 + height * j + bottomMargin], + if (isChidori && isChidoriLine) { + chidoriLength = width / 2 + intvHor + } + + let square = [ + [moduleX - widthMargin - chidoriLength, moduleY + heightMargin], + [moduleX - widthMargin - chidoriLength, moduleY + height + heightMargin], + [moduleX - width - widthMargin - chidoriLength, moduleY + height + heightMargin], + [moduleX - width - widthMargin - chidoriLength, moduleY + heightMargin], + [moduleX - widthMargin - chidoriLength, moduleY + heightMargin], ] let squarePolygon = turf.polygon([square]) let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) - // if (disjointFromTrestle && isDisjoint) { moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id, moduleInfo: module } let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) @@ -1168,32 +1256,454 @@ export function useModuleBasicSetting(tabNum) { let isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) if (disjointFromTrestle && isDisjoint) { - if (index > 0) { - setupModule.forEach((item) => { - const isOverlap = item.some((item2) => turf.booleanOverlap(squarePolygon, polygonToTurfPolygon(item2, true))) - if (!isOverlap) { - canvas?.add(tempModule) - moduleSetupArray.push(tempModule) - moduleArray.push(tempModule) - canvas.renderAll() - } - }) - } else { - //최초 한번은 그냥 그린다 - //겹치는지 확인해서 포함된 모듈만 그린다 - canvas?.add(tempModule) - moduleSetupArray.push(tempModule) - moduleArray.push(tempModule) - canvas.renderAll() - } + canvas?.add(tempModule) + moduleSetupArray.push(tempModule) + moduleArray.push(tempModule) + canvas.renderAll() + + isInstall = true + + // if (j === 0) { + // let startCircle = new fabric.Rect({ + // left: surfaceMaxLines.left.x1, + // top: installedLastHeightCoord, + // stroke: 'red', + // strokeWidth: 1, + // width: 5, + // height: 5, + // fill: 'red', + // originX: 'center', + // originY: 'center', + // }) + // canvas.add(startCircle) + // } + + //마지막에 설치된 모듈의 Y 좌표 + installedLastHeightCoord = moduleY + height + heightMargin } else { //디버깅용 - // tempModule.set({ fill: 'rgba(255,190,41, 0.4)', stroke: 'black', strokeWidth: 1 }) + // tempModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) // canvas?.add(tempModule) // canvas.renderAll() } } + if (isInstall) { + ++installedModuleHeightCount + } } + + // checkedModule.forEach((module, index) => { + // const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) + // const flowLines = getFlowLines(moduleSetupSurface, height) + // let startPoint = flowLines.top + + // // if (flowLines.top.type === 'flat' && flowLines.right.type === 'curve') { + // // startPoint = flowLines.right + // // } + + // const moduleArray = [] + + // if (isCenter) { + // //중앙배치일 경우에는 계산한다 + // if (flowLines.top.type === 'flat' && flowLines.left.type === 'flat' && flowLines.right.type === 'flat') { + // //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 + // const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 + // const halfModuleWidthLength = width / 2 + // startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } + + // if (flowLines.bottom.type === 'flat') { + // //상단까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 + // const heightLength = Math.abs(flowLines.left.y1 - flowLines.left.y2) //옆에에 길이에서 반을 가른다 + // const heightMargin = Math.abs(heightLength - height * Math.floor(heightLength / height)) / 2 + // startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength, y1: startPoint.y1 - heightMargin } + // } + // } + // } + // // else { + // // //중앙배치가 아닐때도 흐름 방향 기준면으로 양면이 직선이면 가운데 배치 + // // if (flowModuleLine.bottom.type === 'flat' && flowModuleLine.left.type === 'flat' && flowModuleLine.right.type === 'flat') { + // // //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 + // // const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 + // // const halfModuleWidthLength = width / 2 + // // startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } + // // } + // // } + + // const maxLeftEndPoint = surfaceMaxLines.left.x1 //최 좌측 + // const maxRightEndPoint = surfaceMaxLines.right.x1 //최 우측 + // const maxBottomEndPoint = surfaceMaxLines.bottom.y1 //최하단 + + // let totalLeftEndPoint = maxLeftEndPoint - startPoint.x1 + // let totalRightEndPoint = maxLeftEndPoint - maxRightEndPoint + // let totalBottomEndPoint = maxBottomEndPoint - startPoint.y1 + // let diffLeftEndPoint = Math.abs(totalLeftEndPoint / width) + // let diffRightEndPoint = Math.ceil(Math.abs(totalRightEndPoint / width)) + // let diffBottomEndPoint = Math.ceil(Math.abs(totalBottomEndPoint / height)) + // let startColPoint = Math.abs(width * Math.ceil(diffLeftEndPoint) - startPoint.x1) + // let tempMaxWidth = isMaxSetup ? width / 2 : width //최대배치인지 확인하려고 넣음 + // if (isMaxSetup) diffRightEndPoint = diffRightEndPoint * 2 //최대배치시 2배로 늘려서 반씩 검사하기위함 + + // startColPoint = Math.round(startColPoint - intvHor * diffRightEndPoint) + + // for (let j = 0; j < diffBottomEndPoint; j++) { + // bottomMargin = j === 0 ? 0 : intvVer * j + // for (let i = 0; i < diffRightEndPoint; i++) { + // leftMargin = i === 0 ? 0 : intvHor * i + // chidoriLength = 0 + // if (isChidori && !isMaxSetup) { + // chidoriLength = j % 2 === 0 ? 0 : width / 2 - intvHor + // } + + // square = [ + // [startColPoint + tempMaxWidth * i + chidoriLength + leftMargin, startPoint.y1 + height * j + bottomMargin], + // [startColPoint + tempMaxWidth * i + chidoriLength + leftMargin, startPoint.y1 + height * j + height + bottomMargin], + // [startColPoint + tempMaxWidth * i + width + chidoriLength + leftMargin, startPoint.y1 + height * j + height + bottomMargin], + // [startColPoint + tempMaxWidth * i + width + chidoriLength + leftMargin, startPoint.y1 + height * j + bottomMargin], + // [startColPoint + tempMaxWidth * i + chidoriLength + leftMargin, startPoint.y1 + height * j + bottomMargin], + // ] + + // let squarePolygon = turf.polygon([square]) + // let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) + // let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) + + // // if (disjointFromTrestle && isDisjoint) { + // 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 isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) + + // if (disjointFromTrestle && isDisjoint) { + // if (index > 0) { + // setupModule.forEach((item) => { + // const isOverlap = item.some((item2) => turf.booleanOverlap(squarePolygon, polygonToTurfPolygon(item2, true))) + // if (!isOverlap) { + // canvas?.add(tempModule) + // moduleSetupArray.push(tempModule) + // moduleArray.push(tempModule) + // canvas.renderAll() + // } + // }) + // } else { + // //최초 한번은 그냥 그린다 + // //겹치는지 확인해서 포함된 모듈만 그린다 + // canvas?.add(tempModule) + // moduleSetupArray.push(tempModule) + // moduleArray.push(tempModule) + // canvas.renderAll() + // } + // } else { + // //디버깅용 + // // tempModule.set({ fill: 'rgba(255,190,41, 0.4)', stroke: 'black', strokeWidth: 1 }) + // // canvas?.add(tempModule) + // // canvas.renderAll() + // } + // } + // } + setupModule.push(moduleArray) + }) + } + + //남, 북과 같은 로직으로 적용하려면 좌우는 열 -> 행 으로 그려야함 + //변수명은 bottom 기준으로 작성하여 동일한 방향으로 진행한다 + const leftFlowSetupModule = ( + surfaceMaxLines, + maxLengthLine, + moduleSetupArray, + moduleSetupSurface, + containsBatchObjects, + isCenter = false, + intvHor, + intvVer, + ) => { + let setupModule = [] + + const trestleDetailData = moduleSetupSurface.trestleDetail //가대 상세 데이터 + const moduleMaxCols = trestleDetailData.moduleMaxCols // 모듈 최대 가로 설치 갯수 + + let installedLastHeightCoord = 0 //마지막으로 설치된 모듈의 좌표 + let installedModuleHeightCount = 0 //마지막으로 설치된 모듈의 카운트 + let isChidoriLine = false + let flowLines + + checkedModule.forEach((module, moduleIndex) => { + const tmpModuleData = trestleDetailData.module.filter((moduleObj) => module.moduleTpCd === moduleObj.moduleTpCd)[0] + //혼합모듈일때는 mixModuleMaxRows 값이 0 이상임 + let moduleMaxRows = tmpModuleData.mixModuleMaxRows === 0 ? tmpModuleData.moduleMaxRows : tmpModuleData.mixModuleMaxRows + + // 혼합모듈 포함 총 모듈 설치 높이 갯수 + const totalModuleMaxRows = tmpModuleData.moduleMaxRows + + //모듈의 넓이 높이를 가져옴 (복시도 촌수 적용) + //1번 깔았던 모듈 기준으로 잡야아함 + const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) + + if (moduleIndex === 0) { + flowLines = getFlowLines(moduleSetupSurface, width) + if (flowLines.left.type === 'curve') { + flowLines = getFlowLines(moduleSetupSurface, height) + } + } + + //육지붕이 아닐때만 넣는다 육지붕일땐 클릭 이벤트에 별도로 넣어놓음 + // let startPoint = flowLines.bottom + const moduleArray = [] + // const moduleMaxRows = module + //밑에가 곡선이면 모듈의 넓이를 가지고 계산한다 + // if (isCenter) { + // //중앙배치일 경우에는 계산한다 + // if (flowLines.bottom.type === 'flat' && flowLines.left.type === 'flat' && flowLines.right.type === 'flat') { + // //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 + // const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 + // const halfModuleWidthLength = width / 2 + // startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } + + // if (flowLines.top.type === 'flat') { + // //상단까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 + // const heightLength = Math.abs(flowLines.left.y1 - flowLines.left.y2) //옆에에 길이에서 반을 가른다 + // const heightMargin = Math.abs(heightLength - height * Math.floor(heightLength / height)) / 2 + // startPoint = { ...startPoint, y1: startPoint.y1 - heightMargin } + // } + // } + // } + //밑에가 평면이면 좌측으로 붙여서 배치 + // if (flowLines.bottom.type === 'flat' && flowLines.left.type === 'curve') { + // startPoint = flowLines.left + // } + + // let leftEnd = new fabric.Circle({ left: surfaceMaxLines.left.x1 - 2.5, top: surfaceMaxLines.left.y1 - 2.5, radius: 5, fill: 'green' }) + // let rightEnd = new fabric.Circle({ left: surfaceMaxLines.right.x1 - 2.5, top: surfaceMaxLines.right.y1 - 2.5, radius: 5, fill: 'green' }) + // let topEnd = new fabric.Circle({ left: surfaceMaxLines.top.x1 - 2.5, top: surfaceMaxLines.top.y1 - 2.5, radius: 5, fill: 'green' }) + + // canvas?.add(leftEnd) + // canvas?.add(rightEnd) + // canvas?.add(topEnd) + + // canvas.renderAll() + + let calcAreaWidth = flowLines.bottom.y1 - flowLines.top.y1 //아래에서 y에서 위를 y를 뺀 가운데를 찾는 로직 + let calcModuleWidthCount = calcAreaWidth / (height + intvHor) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 + let calcMaxModuleWidthCount = calcModuleWidthCount > moduleMaxCols ? moduleMaxCols : calcModuleWidthCount //최대 모듈 단수가 있기 때문에 최대 단수보다 카운트가 크면 최대 단수로 씀씀 + // let totalModuleWidthCount = isChidori ? Math.abs(calcMaxModuleWidthCount) : Math.floor(calcMaxModuleWidthCount) //치조배치일경우는 한개 더 넣는다 + let totalModuleWidthCount = Math.floor(calcMaxModuleWidthCount) //치조배치일경우는 한개 더 넣는다 + + // let calcAreaHeight = flowLines.bottom.y1 - flowLines.top.y1 + // let calcModuleHeightCount = calcAreaHeight / (height + intvVer) + + let calcStartPoint = flowLines.bottom.type === 'flat' ? (calcAreaWidth - totalModuleWidthCount * height) / 2 : 0 //반씩 나눠서 중앙에 맞춤 left 높이 기준으로 양변이 직선일때만 가운데 정렬 + let startPointX = flowLines.top.y1 + calcStartPoint //시작점을 만든다 + + //근데 양변이 곡선이면 중앙에 맞추기 위해 아래와 위의 길이를 재서 모듈의 길이를 나눠서 들어갈수 있는 갯수가 동일하면 가운데로 정렬 시킨다 + if (flowLines.top.type === 'curve' && flowLines.bottom.type === 'curve') { + // const calcTopWidth = Math.abs(flowLines.right.y1 - flowLines.right.y2) + // const calcTopModuleWidthCount = calcTopWidth / (height + intvVer) + + // if (Math.floor(calcMaxModuleWidthCount) === Math.floor(calcTopModuleWidthCount)) { + startPointX = flowLines.top.y1 + (calcAreaWidth - totalModuleWidthCount * height) / 2 + // } + } + + let heightMargin = 0 + let widthMargin = 0 + let chidoriLength = 0 + + //첫번재 모듈 설치 후 두번째 모듈을 몇개까지 설치 할 수 있는지 계산 + if (moduleIndex > 0) { + moduleMaxRows = totalModuleMaxRows - installedModuleHeightCount //두번째 모듈일때 + isChidoriLine = installedModuleHeightCount % 2 != 0 ? true : false //첫번째에서 짝수에서 끝났으면 홀수는 치도리가 아님 짝수는 치도리 + } + + let isInstall = false + + for (let i = 0; i < moduleMaxRows; i++) { + let moduleY = flowLines.left.x1 + width * i + 1 //살짝 여유를 준다 + + //두번째 모듈 -> 혼합일 경우의 설치될 모듈 높이를 계산 + if (moduleIndex > 0) { + moduleY = installedLastHeightCoord + intvHor + } + + //전체 설치 간으 모듈이랑 같으면 반복을 멈춘다 + if (totalModuleMaxRows === installedModuleHeightCount) { + break + } + + //첫번째는 붙여서 두번째는 마진을 주고 설치 + heightMargin = i === 0 ? 0 : intvHor * i + + for (let j = 0; j < totalModuleWidthCount; j++) { + let moduleX = startPointX + height * j + 1 //5정도 마진을 준다 + widthMargin = j === 0 ? 0 : intvVer * j // 가로 마진값 + chidoriLength = 0 //치도리가 아니여도 기본값을 5정도 준다 + if (isChidori && !isMaxSetup) { + chidoriLength = installedModuleHeightCount % 2 == 0 ? 0 : height / 2 - intvVer + } + + //치도리 일때 는 짝수(1 기준) 일때만 치도리 라인으로 본다 + if (isChidori && isChidoriLine) { + chidoriLength = width / 2 - height + } + + let square = [ + [moduleY + heightMargin, moduleX + height + widthMargin + chidoriLength], + [moduleY + heightMargin, moduleX + widthMargin + chidoriLength], + [moduleY + width + heightMargin, moduleX + widthMargin + chidoriLength], + [moduleY + width + heightMargin, moduleX + height + widthMargin + chidoriLength], + [moduleY + heightMargin, moduleX + height + widthMargin + chidoriLength], + ] + + let squarePolygon = turf.polygon([square]) + let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) + let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) + + 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 isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) + + if (disjointFromTrestle && isDisjoint) { + //최초 한번은 그냥 그린다 + //겹치는지 확인해서 포함된 모듈만 그린다 + canvas?.add(tempModule) + moduleSetupArray.push(tempModule) + moduleArray.push(tempModule) + canvas.renderAll() + + // ++installedModuleHeightCount + + isInstall = true + //마지막에 설치된 모듈의 Y 좌표 + + //디버깅용 + // if (j === 0) { + // let startCircle = new fabric.Rect({ + // left: surfaceMaxLines.left.x1, + // top: installedLastHeightCoord, + // stroke: 'red', + // strokeWidth: 1, + // width: 5, + // height: 5, + // fill: 'red', + // originX: 'center', + // originY: 'center', + // }) + // canvas.add(startCircle) + // } + } else { + //디버깅용 + // tempModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) + // canvas?.add(tempModule) + // canvas.renderAll() + } + } + + installedLastHeightCoord = moduleY + width + widthMargin + + if (isInstall) { + ++installedModuleHeightCount + } + } + + // checkedModule.forEach((module, index) => { + // const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) + // let flowLines = getFlowLines(moduleSetupSurface, width) + // //육지붕이 아닐때만 넣는다 육지붕일땐 클릭 이벤트에 별도로 넣어놓음 + // let startPoint = flowLines.left + // const moduleArray = [] + + // // if (flowLines.left.type === 'flat') { + // // const tempPoint = { ...flowLines.top } + // // startPoint = { ...flowLines.top, x1: tempPoint.x2, x2: tempPoint.x1 } + // // } else { + // // flowLines = getFlowLines(moduleSetupSurface, height) + // // const tempPoint = { ...flowLines.left } + // // startPoint = { ...flowLines.left, x1: tempPoint.x1 + 5, x2: tempPoint.x2, y1: tempPoint.y1 - 5 } + // // } + + // //중앙배치일 경우에는 계산한다 + // if (isCenter) { + // if (flowLines.left.type === 'flat' && flowLines.bottom.type === 'flat' && flowLines.top.type === 'flat') { + // //좌측 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 + // const halfWidthLength = Math.abs(startPoint.y1 + startPoint.y2) / 2 //밑에 길이에서 반을 가른다 + // const halfModuleWidthLength = height / 2 + // startPoint = { ...startPoint, y1: halfWidthLength - halfModuleWidthLength } + // if (flowLines.right.type === 'flat') { + // //우측까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 + // const widthLength = Math.abs(flowLines.top.x1 - flowLines.top.x2) //옆에에 길이에서 반을 가른다 + // const widthMargin = Math.abs(widthLength - width * Math.floor(widthLength / width)) / 2 + // startPoint = { ...startPoint, x1: startPoint.x1 + widthMargin } + // } + // } + // } + + // const maxRightEndPoint = surfaceMaxLines.right.x1 //최 우측 + // const maxTopEndPoint = surfaceMaxLines.top.y1 //최 상단 + // const maxBottomEndPoint = surfaceMaxLines.bottom.y1 //최하단 + + // let totalTopEndPoint = Math.abs(maxTopEndPoint - startPoint.y1) //전체 높이에서 현재 높이를 뺌 + // let diffTopEndPoint = Math.abs(totalTopEndPoint / height) + // let totalHeight = Math.ceil(Math.abs(maxBottomEndPoint - maxTopEndPoint) / height) + // let totalWidth = Math.abs(startPoint.x1 - maxRightEndPoint) / width + // let startRowPoint = startPoint.y1 - height * Math.ceil(diffTopEndPoint) + + // let tempMaxHeight = isMaxSetup ? height / 2 : height //최대배치인지 확인하려고 넣음 + // if (isMaxSetup) totalHeight = totalHeight * 2 //최대배치시 2배로 늘려 서 반씩 검사 + + // for (let i = 0; i <= totalWidth; i++) { + // bottomMargin = i === 0 ? 0 : intvHor * i + // for (let j = 0; j < totalHeight; j++) { + // leftMargin = j === 0 ? 0 : intvVer * j + // chidoriLength = 0 + // if (isChidori && !isMaxSetup) { + // chidoriLength = i % 2 === 0 ? 0 : height / 2 + // } + + // square = [ + // [startPoint.x1 + width * i + bottomMargin, startRowPoint + tempMaxHeight * j + leftMargin - chidoriLength], + // [startPoint.x1 + width * i + width + bottomMargin, startRowPoint + tempMaxHeight * j + leftMargin - chidoriLength], + // [startPoint.x1 + width * i + width + bottomMargin, startRowPoint + tempMaxHeight * j + height + leftMargin - chidoriLength], + // [startPoint.x1 + width * i + bottomMargin, startRowPoint + tempMaxHeight * j + height + leftMargin - chidoriLength], + // [startPoint.x1 + width * i + bottomMargin, startRowPoint + tempMaxHeight * j + leftMargin - chidoriLength], + // ] + + // let squarePolygon = turf.polygon([square]) + // let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) + // let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) + + // // if (disjointFromTrestle && isDisjoint) { + // 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 isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) + + // if (disjointFromTrestle && isDisjoint) { + // if (index > 0) { + // setupModule.forEach((item) => { + // const isOverlap = item.some((item2) => turf.booleanOverlap(squarePolygon, polygonToTurfPolygon(item2, true))) + // if (!isOverlap) { + // canvas?.add(tempModule) + // moduleSetupArray.push(tempModule) + // moduleArray.push(tempModule) + // canvas.renderAll() + // } + // }) + // } else { + // //최초 한번은 그냥 그린다 + // //겹치는지 확인해서 포함된 모듈만 그린다 + // canvas?.add(tempModule) + // moduleSetupArray.push(tempModule) + // moduleArray.push(tempModule) + // canvas.renderAll() + // } + // } else { + // //디버깅용 + // // tempModule.set({ fill: 'rgba(255,190,41, 0.4)', stroke: 'black', strokeWidth: 1 }) + // // canvas?.add(tempModule) + // // canvas.renderAll() + // } + // } + // } setupModule.push(moduleArray) }) } @@ -1210,108 +1720,291 @@ export function useModuleBasicSetting(tabNum) { ) => { let setupModule = [] - checkedModule.forEach((module, index) => { + const trestleDetailData = moduleSetupSurface.trestleDetail //가대 상세 데이터 + const moduleMaxCols = trestleDetailData.moduleMaxCols // 모듈 최대 가로 설치 갯수 + + let installedLastHeightCoord = 0 //마지막으로 설치된 모듈의 좌표 + let installedModuleHeightCount = 0 //마지막으로 설치된 모듈의 카운트 + let isChidoriLine = false + let flowLines + + checkedModule.forEach((module, moduleIndex) => { + const tmpModuleData = trestleDetailData.module.filter((moduleObj) => module.moduleTpCd === moduleObj.moduleTpCd)[0] + //혼합모듈일때는 mixModuleMaxRows 값이 0 이상임 + let moduleMaxRows = tmpModuleData.mixModuleMaxRows === 0 ? tmpModuleData.moduleMaxRows : tmpModuleData.mixModuleMaxRows + + // 혼합모듈 포함 총 모듈 설치 높이 갯수 + const totalModuleMaxRows = tmpModuleData.moduleMaxRows + + //모듈의 넓이 높이를 가져옴 (복시도 촌수 적용) + //1번 깔았던 모듈 기준으로 잡야아함 const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) - let flowLines = getFlowLines(moduleSetupSurface, width) - let startPoint = flowLines.right - // if (flowLines.right.type === 'flat') { - // const tempPoint = { ...flowLines.bottom } - // startPoint = { ...flowLines.bottom, x1: tempPoint.x2, x2: tempPoint.x1 } - // } else { - // flowLines = getFlowLines(moduleSetupSurface, height) - // const tempPoint = { ...flowLines.right } - // startPoint = { ...flowLines.right, x1: tempPoint.x1 - 5, x2: tempPoint.x2, y1: tempPoint.y1 + 5 } - // } - - // console.log('startPoint', startPoint) - - const moduleArray = [] - - if (isCenter) { - if (flowLines.left.type === 'flat' && flowLines.bottom.type === 'flat' && flowLines.top.type === 'flat') { - //좌측 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 - const halfWidthLength = Math.abs(startPoint.y1 + startPoint.y2) / 2 //밑에 길이에서 반을 가른다 - const halfModuleWidthLength = height / 2 - startPoint = { ...startPoint, y1: halfWidthLength + halfModuleWidthLength } - - if (flowLines.right.type === 'flat') { - //우측까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 - const widthLength = Math.abs(flowLines.top.x1 - flowLines.top.x2) //옆에에 길이에서 반을 가른다 - const widthMargin = Math.abs(widthLength - width * Math.floor(widthLength / width)) / 2 - startPoint = { ...startPoint, x1: startPoint.x1 - widthMargin } - } + if (moduleIndex === 0) { + flowLines = getFlowLines(moduleSetupSurface, width) + if (flowLines.right.type === 'curve') { + flowLines = getFlowLines(moduleSetupSurface, height) } } - const maxLeftEndPoint = surfaceMaxLines.left.x1 //최 좌측 - const maxTopEndPoint = surfaceMaxLines.top.y1 //최 상단 - const maxBottomEndPoint = surfaceMaxLines.bottom.y1 //최하단 + //육지붕이 아닐때만 넣는다 육지붕일땐 클릭 이벤트에 별도로 넣어놓음 + // let startPoint = flowLines.bottom + const moduleArray = [] + // const moduleMaxRows = module + //밑에가 곡선이면 모듈의 넓이를 가지고 계산한다 + // if (isCenter) { + // //중앙배치일 경우에는 계산한다 + // if (flowLines.bottom.type === 'flat' && flowLines.left.type === 'flat' && flowLines.right.type === 'flat') { + // //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 + // const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 + // const halfModuleWidthLength = width / 2 + // startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } - let totalTopEndPoint = Math.abs(maxTopEndPoint - startPoint.y1) //전체 높이에서 현재 높이를 뺌 - let diffTopEndPoint = Math.abs(totalTopEndPoint / height) - let totalHeight = Math.ceil(Math.abs(maxBottomEndPoint - maxTopEndPoint) / height) - let totalWidth = Math.abs(startPoint.x1 - maxLeftEndPoint) / width - let startRowPoint = startPoint.y1 - height * Math.ceil(diffTopEndPoint) - 4 // -3으로 위치살짝 보정1 + // if (flowLines.top.type === 'flat') { + // //상단까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 + // const heightLength = Math.abs(flowLines.left.y1 - flowLines.left.y2) //옆에에 길이에서 반을 가른다 + // const heightMargin = Math.abs(heightLength - height * Math.floor(heightLength / height)) / 2 + // startPoint = { ...startPoint, y1: startPoint.y1 - heightMargin } + // } + // } + // } + //밑에가 평면이면 좌측으로 붙여서 배치 + // if (flowLines.bottom.type === 'flat' && flowLines.left.type === 'curve') { + // startPoint = flowLines.left + // } - let tempMaxHeight = isMaxSetup ? height / 2 : height //최대배치인지 확인하려고 넣음 - if (isMaxSetup) totalHeight = totalHeight * 2 //최대배치시 2배로 늘려서 반씩 검사 + // let leftEnd = new fabric.Circle({ left: surfaceMaxLines.left.x1 - 2.5, top: surfaceMaxLines.left.y1 - 2.5, radius: 5, fill: 'green' }) + // let bottomEnd = new fabric.Circle({ left: surfaceMaxLines.bottom.x1 - 2.5, top: surfaceMaxLines.bottom.y1 - 2.5, radius: 5, fill: 'green' }) + // let topEnd = new fabric.Circle({ left: surfaceMaxLines.top.x1 - 2.5, top: surfaceMaxLines.top.y1 - 2.5, radius: 5, fill: 'green' }) - for (let i = 0; i <= totalWidth; i++) { - bottomMargin = i === 0 ? 0 : -(intvHor * i) - for (let j = 0; j < totalHeight; j++) { - leftMargin = j === 0 ? 0 : intvVer * j + // canvas?.add(leftEnd) + // canvas?.add(bottomEnd) + // canvas?.add(topEnd) - chidoriLength = 0 + // canvas.renderAll() + + let calcAreaWidth = flowLines.bottom.y1 - flowLines.top.y1 //아래에서 y에서 위를 y를 뺀 가운데를 찾는 로직 + let calcModuleWidthCount = calcAreaWidth / (height + intvHor) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 + let calcMaxModuleWidthCount = calcModuleWidthCount > moduleMaxCols ? moduleMaxCols : calcModuleWidthCount //최대 모듈 단수가 있기 때문에 최대 단수보다 카운트가 크면 최대 단수로 씀씀 + // let totalModuleWidthCount = isChidori ? Math.abs(calcMaxModuleWidthCount) : Math.floor(calcMaxModuleWidthCount) //치조배치일경우는 한개 더 넣는다 + let totalModuleWidthCount = Math.floor(calcMaxModuleWidthCount) //치조배치일경우는 한개 더 넣는다 + + // let calcAreaHeight = flowLines.bottom.y1 - flowLines.top.y1 + // let calcModuleHeightCount = calcAreaHeight / (height + intvVer) + + let calcStartPoint = flowLines.top.type === 'flat' ? (calcAreaWidth - totalModuleWidthCount * height) / 2 : 0 //반씩 나눠서 중앙에 맞춤 left 높이 기준으로 양변이 직선일때만 가운데 정렬 + let startPointX = flowLines.bottom.y2 - calcStartPoint //시작점을 만든다 + + //근데 양변이 곡선이면 중앙에 맞추기 위해 아래와 위의 길이를 재서 모듈의 길이를 나눠서 들어갈수 있는 갯수가 동일하면 가운데로 정렬 시킨다 + if (flowLines.top.type === 'curve' && flowLines.bottom.type === 'curve') { + // const calcTopWidth = Math.abs(flowLines.right.y1 - flowLines.right.y2) + // const calcTopModuleWidthCount = calcTopWidth / (height + intvVer) + + // if (Math.floor(calcMaxModuleWidthCount) === Math.floor(calcTopModuleWidthCount)) { + startPointX = flowLines.bottom.y2 - (calcAreaWidth - totalModuleWidthCount * height) / 2 + // } + } + + let heightMargin = 0 + let widthMargin = 0 + let chidoriLength = 0 + + //첫번재 모듈 설치 후 두번째 모듈을 몇개까지 설치 할 수 있는지 계산 + if (moduleIndex > 0) { + moduleMaxRows = totalModuleMaxRows - installedModuleHeightCount //두번째 모듈일때 + isChidoriLine = installedModuleHeightCount % 2 != 0 ? true : false //첫번째에서 짝수에서 끝났으면 홀수는 치도리가 아님 짝수는 치도리 + } + + let isInstall = false + + for (let i = 0; i < moduleMaxRows; i++) { + let moduleY = flowLines.right.x1 - width * i - 1 //살짝 여유를 준다 + + //두번째 모듈 -> 혼합일 경우의 설치될 모듈 높이를 계산 + if (moduleIndex > 0) { + moduleY = installedLastHeightCoord - intvHor + } + + //전체 설치 간으 모듈이랑 같으면 반복을 멈춘다 + if (totalModuleMaxRows === installedModuleHeightCount) { + break + } + + //첫번째는 붙여서 두번째는 마진을 주고 설치 + heightMargin = i === 0 ? 0 : intvHor * i + + for (let j = 0; j < totalModuleWidthCount; j++) { + let moduleX = startPointX - height * j - 1 //5정도 마진을 준다 + widthMargin = j === 0 ? 0 : intvVer * j // 가로 마진값 + chidoriLength = 0 //치도리가 아니여도 기본값을 5정도 준다 if (isChidori && !isMaxSetup) { - chidoriLength = i % 2 === 0 ? 0 : height / 2 - intvHor + chidoriLength = installedModuleHeightCount % 2 == 0 ? 0 : height / 2 - intvVer } - square = [ - [startPoint.x1 - width * i + bottomMargin, startRowPoint - intvHor + tempMaxHeight * j + leftMargin + chidoriLength], - [startPoint.x1 - width * i - width + bottomMargin, startRowPoint - intvHor + tempMaxHeight * j + leftMargin + chidoriLength], - [startPoint.x1 - width * i - width + bottomMargin, startRowPoint - intvHor + tempMaxHeight * j + height + leftMargin + chidoriLength], - [startPoint.x1 - width * i + bottomMargin, startRowPoint - intvHor + tempMaxHeight * j + height + leftMargin + chidoriLength], - [startPoint.x1 - width * i + bottomMargin, startRowPoint - intvHor + tempMaxHeight * j + leftMargin + chidoriLength], + //치도리 일때 는 짝수(1 기준) 일때만 치도리 라인으로 본다 + if (isChidori && isChidoriLine) { + chidoriLength = width / 2 - height + } + + let square = [ + [moduleY - heightMargin, moduleX - height - widthMargin - chidoriLength], + [moduleY - heightMargin, moduleX - widthMargin - chidoriLength], + [moduleY - width - heightMargin, moduleX - widthMargin - chidoriLength], + [moduleY - width - heightMargin, moduleX - height - widthMargin - chidoriLength], + [moduleY - heightMargin, moduleX - height - widthMargin - chidoriLength], ] let squarePolygon = turf.polygon([square]) let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) - // if (disjointFromTrestle && isDisjoint) { 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 isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) if (disjointFromTrestle && isDisjoint) { - if (index > 0) { - setupModule.forEach((item) => { - const isOverlap = item.some((item2) => turf.booleanOverlap(squarePolygon, polygonToTurfPolygon(item2, true))) - if (!isOverlap) { - canvas?.add(tempModule) - moduleSetupArray.push(tempModule) - moduleArray.push(tempModule) - canvas.renderAll() - } - }) - } else { - //최초 한번은 그냥 그린다 - //겹치는지 확인해서 포함된 모듈만 그린다 - canvas?.add(tempModule) - moduleSetupArray.push(tempModule) - moduleArray.push(tempModule) - canvas.renderAll() - } + //최초 한번은 그냥 그린다 + //겹치는지 확인해서 포함된 모듈만 그린다 + canvas?.add(tempModule) + moduleSetupArray.push(tempModule) + moduleArray.push(tempModule) + canvas.renderAll() + + // ++installedModuleHeightCount + + isInstall = true + //마지막에 설치된 모듈의 Y 좌표 + + // if (j === 0) { + // let startCircle = new fabric.Rect({ + // left: surfaceMaxLines.left.x1, + // top: installedLastHeightCoord, + // stroke: 'red', + // strokeWidth: 1, + // width: 5, + // height: 5, + // fill: 'red', + // originX: 'center', + // originY: 'center', + // }) + // canvas.add(startCircle) + // } } else { //디버깅용 - // tempModule.set({ fill: 'rgba(255,190,41, 0.4)', stroke: 'black', strokeWidth: 1 }) + // tempModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) // canvas?.add(tempModule) // canvas.renderAll() } } + + installedLastHeightCoord = moduleY + height + heightMargin + + if (isInstall) { + ++installedModuleHeightCount + } } + + // checkedModule.forEach((module, index) => { + // const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) + // let flowLines = getFlowLines(moduleSetupSurface, width) + // //육지붕이 아닐때만 넣는다 육지붕일땐 클릭 이벤트에 별도로 넣어놓음 + // let startPoint = flowLines.left + // const moduleArray = [] + + // // if (flowLines.left.type === 'flat') { + // // const tempPoint = { ...flowLines.top } + // // startPoint = { ...flowLines.top, x1: tempPoint.x2, x2: tempPoint.x1 } + // // } else { + // // flowLines = getFlowLines(moduleSetupSurface, height) + // // const tempPoint = { ...flowLines.left } + // // startPoint = { ...flowLines.left, x1: tempPoint.x1 + 5, x2: tempPoint.x2, y1: tempPoint.y1 - 5 } + // // } + + // //중앙배치일 경우에는 계산한다 + // if (isCenter) { + // if (flowLines.left.type === 'flat' && flowLines.bottom.type === 'flat' && flowLines.top.type === 'flat') { + // //좌측 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 + // const halfWidthLength = Math.abs(startPoint.y1 + startPoint.y2) / 2 //밑에 길이에서 반을 가른다 + // const halfModuleWidthLength = height / 2 + // startPoint = { ...startPoint, y1: halfWidthLength - halfModuleWidthLength } + // if (flowLines.right.type === 'flat') { + // //우측까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 + // const widthLength = Math.abs(flowLines.top.x1 - flowLines.top.x2) //옆에에 길이에서 반을 가른다 + // const widthMargin = Math.abs(widthLength - width * Math.floor(widthLength / width)) / 2 + // startPoint = { ...startPoint, x1: startPoint.x1 + widthMargin } + // } + // } + // } + + // const maxRightEndPoint = surfaceMaxLines.right.x1 //최 우측 + // const maxTopEndPoint = surfaceMaxLines.top.y1 //최 상단 + // const maxBottomEndPoint = surfaceMaxLines.bottom.y1 //최하단 + + // let totalTopEndPoint = Math.abs(maxTopEndPoint - startPoint.y1) //전체 높이에서 현재 높이를 뺌 + // let diffTopEndPoint = Math.abs(totalTopEndPoint / height) + // let totalHeight = Math.ceil(Math.abs(maxBottomEndPoint - maxTopEndPoint) / height) + // let totalWidth = Math.abs(startPoint.x1 - maxRightEndPoint) / width + // let startRowPoint = startPoint.y1 - height * Math.ceil(diffTopEndPoint) + + // let tempMaxHeight = isMaxSetup ? height / 2 : height //최대배치인지 확인하려고 넣음 + // if (isMaxSetup) totalHeight = totalHeight * 2 //최대배치시 2배로 늘려 서 반씩 검사 + + // for (let i = 0; i <= totalWidth; i++) { + // bottomMargin = i === 0 ? 0 : intvHor * i + // for (let j = 0; j < totalHeight; j++) { + // leftMargin = j === 0 ? 0 : intvVer * j + // chidoriLength = 0 + // if (isChidori && !isMaxSetup) { + // chidoriLength = i % 2 === 0 ? 0 : height / 2 + // } + + // square = [ + // [startPoint.x1 + width * i + bottomMargin, startRowPoint + tempMaxHeight * j + leftMargin - chidoriLength], + // [startPoint.x1 + width * i + width + bottomMargin, startRowPoint + tempMaxHeight * j + leftMargin - chidoriLength], + // [startPoint.x1 + width * i + width + bottomMargin, startRowPoint + tempMaxHeight * j + height + leftMargin - chidoriLength], + // [startPoint.x1 + width * i + bottomMargin, startRowPoint + tempMaxHeight * j + height + leftMargin - chidoriLength], + // [startPoint.x1 + width * i + bottomMargin, startRowPoint + tempMaxHeight * j + leftMargin - chidoriLength], + // ] + + // let squarePolygon = turf.polygon([square]) + // let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) + // let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) + + // // if (disjointFromTrestle && isDisjoint) { + // 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 isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) + + // if (disjointFromTrestle && isDisjoint) { + // if (index > 0) { + // setupModule.forEach((item) => { + // const isOverlap = item.some((item2) => turf.booleanOverlap(squarePolygon, polygonToTurfPolygon(item2, true))) + // if (!isOverlap) { + // canvas?.add(tempModule) + // moduleSetupArray.push(tempModule) + // moduleArray.push(tempModule) + // canvas.renderAll() + // } + // }) + // } else { + // //최초 한번은 그냥 그린다 + // //겹치는지 확인해서 포함된 모듈만 그린다 + // canvas?.add(tempModule) + // moduleSetupArray.push(tempModule) + // moduleArray.push(tempModule) + // canvas.renderAll() + // } + // } else { + // //디버깅용 + // // tempModule.set({ fill: 'rgba(255,190,41, 0.4)', stroke: 'black', strokeWidth: 1 }) + // // canvas?.add(tempModule) + // // canvas.renderAll() + // } + // } + // } setupModule.push(moduleArray) }) } @@ -1516,6 +2209,7 @@ export function useModuleBasicSetting(tabNum) { 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, @@ -1524,8 +2218,8 @@ export function useModuleBasicSetting(tabNum) { // console.log(`index ${index} : finalLine`, pointX1, pointY1, pointX2, pointY2) - canvas?.add(finalLine) - canvas?.renderAll() + // canvas?.add(finalLine) + // canvas?.renderAll() let rtnObj //평평하면 @@ -1562,7 +2256,6 @@ export function useModuleBasicSetting(tabNum) { rtnObjArray.push(rtnObj) }) - return rtnObjArray } @@ -1642,13 +2335,14 @@ export function useModuleBasicSetting(tabNum) { 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() + // canvas?.add(finalLine) + // canvas?.renderAll() let rtnObj //평평하면 @@ -1836,7 +2530,7 @@ export function useModuleBasicSetting(tabNum) { let tmpHeight = flowDirection === 'south' || flowDirection === 'north' ? moduleHeight : moduleWidth let { width, height } = - canvasSetting.roofSizeSet === '1' + canvasSetting.roofSizeSet == '1' ? calculateVisibleModuleHeight(tmpWidth, tmpHeight, getDegreeByChon(moduleSetupSurfaces[i].roofMaterial.pitch), flowDirection) : { width: tmpWidth, height: tmpHeight } @@ -2622,7 +3316,7 @@ export function useModuleBasicSetting(tabNum) { 10 } - return canvasSetting.roofSizeSet === '1' + return canvasSetting.roofSizeSet == '1' ? calculateVisibleModuleHeight(tmpWidth, tmpHeight, getDegreeByChon(moduleSetupSurface.roofMaterial.pitch), moduleSetupSurface.direction) : { width: tmpWidth, height: tmpHeight } }