qcast-front/src/hooks/module/useTrestle.js

2804 lines
106 KiB
JavaScript

import { useRecoilValue } from 'recoil'
import { canvasState, currentAngleTypeSelector } from '@/store/canvasAtom'
import { POLYGON_TYPE, TRESTLE_MATERIAL } from '@/common/common'
import { moduleSelectionDataState } from '@/store/selectedModuleOptions'
import { getDegreeByChon } from '@/util/canvas-util'
import { v4 as uuidv4 } from 'uuid'
import { useMasterController } from '@/hooks/common/useMasterController'
import { basicSettingState, trestleDisplaySelector } from '@/store/settingAtom'
import { useSwal } from '@/hooks/useSwal'
import { useContext } from 'react'
import { QcastContext } from '@/app/QcastProvider'
import { useCircuitTrestle } from '@/hooks/useCirCuitTrestle'
// 모듈간 같은 행, 열의 마진이 10 이하인 경우는 같은 행, 열로 간주
const MODULE_MARGIN = 10
// 회로 및 가대설정
export const useTrestle = () => {
const canvas = useRecoilValue(canvasState)
const moduleSelectionData = useRecoilValue(moduleSelectionDataState) //다음으로 넘어가는 최종 데이터
const { getQuotationItem } = useMasterController()
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
const roofSizeSet = useRecoilValue(basicSettingState).roofSizeSet
const isTrestleDisplay = useRecoilValue(trestleDisplaySelector)
const { swalFire } = useSwal()
const { setIsGlobalLoading } = useContext(QcastContext)
const { getSelectedPcsItemList } = useCircuitTrestle()
const { resetCircuits } = useCircuitTrestle()
const apply = () => {
const notAllocationModules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE && !obj.circuit)
if (notAllocationModules.length > 0) {
swalFire({ text: '回路番号が設定されていないモジュールがあります。 番号を設定しなおすか、 パネルを削除してください。', icon: 'error' })
setIsGlobalLoading(false)
return
}
try {
//처마력바가 체크되어 있는 경우 exposedBottomPoints를 이용해 처마력바 그려줘야함.
// exposedBottomPoints는 노출 최하면 들의 centerPoint 배열.
const surfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
// 기존 eaveBar를 삭제
canvas.getObjects().forEach((obj) => {
if (obj.name === 'eaveBar' || obj.name === 'rack' || obj.name === 'halfEaveBar' || obj.name === 'smartRack') {
canvas.remove(obj)
}
})
canvas.getObjects().forEach((obj) => {
if (obj.name === 'bracket') {
canvas.remove(obj)
}
})
surfaces.forEach((surface) => {
const parent = canvas.getObjects().find((obj) => obj.id === surface.parentId)
const roofMaterialIndex = parent.roofMaterial.index
if (+roofSizeSet === 3) {
return
}
const construction = moduleSelectionData?.roofConstructions?.find((construction) => construction.roofIndex === roofMaterialIndex).construction
if (!construction) {
swalFire({ text: 'construction 존재안함', icon: 'error' })
return
}
const plvrYn = construction.plvrYn
let moduleRowsTotCnt = 0
let isEaveBar = construction.setupCover
let isSnowGuard = construction.setupSnowCover
const direction = parent.direction
const rack = surface.trestleDetail.rack
let { rackQty, rackIntvlPct, rackYn, cvrPlvrYn, lessSupFitIntvlPct, lessSupFitQty } = surface.trestleDetail
if (!rack && lessSupFitIntvlPct === 0 && lessSupFitQty === 0) {
//25/02/06 가대없음의 경우 랙정보가 없음
return
}
let rackInfos = []
if (rack) {
rackInfos = Object.keys(rack).map((key) => {
return { key, value: rack[key] }
})
}
// 모듈들의 centerPoint들을 이용해 각 모듈의 정보(가장 아랫라인 모듈, 가장 윗라인 모듈, 접면, 반접면 등 계산)
const result = calculateForApi(surface)
if (!result) {
return
}
const centerPoints = result.centerPoints
const exposedBottomModules = [] // 아래 두면이 모두 노출 되어있는 경우
const leftExposedHalfBottomModules = [] // 왼쪽 면만 노출되어있는 경우
const rightExposedHalfBottomPoints = [] // 오른쪽 면만 노출되어 있는 경우
const leftExposedHalfTopModules = [] // 왼쪽 면만 노출되어 있는 경우
const rightExposedHalfTopPoints = [] // 오른쪽 면만 노출되어 있는 경우
const modules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE)
modules.forEach((module) => {
const { x, y } = module.getCenterPoint()
const isExposedBottom = result.exposedBottomPoints.some((point) => Math.abs(point.x - x) < 2 && Math.abs(point.y - y) < 2)
const isLeftExposedHalfBottom = result.leftExposedHalfBottomPoints.some((point) => Math.abs(point.x - x) < 2 && Math.abs(point.y - y) < 2)
const isRightExposedHalfBottom = result.rightExposedHalfBottomPoints.some((point) => Math.abs(point.x - x) < 2 && Math.abs(point.y - y) < 2)
const isRightExposedHalfTop = result.rightExposedHalfTopPoints.some((point) => Math.abs(point.x - x) < 2 && Math.abs(point.y - y) < 2)
const isLeftExposedHalfTop = result.leftExposedHalfTopPoints.some((point) => Math.abs(point.x - x) < 2 && Math.abs(point.y - y) < 2)
if (isExposedBottom) {
exposedBottomModules.push(module)
}
if (isLeftExposedHalfBottom) {
leftExposedHalfBottomModules.push(module)
}
if (isRightExposedHalfBottom) {
rightExposedHalfBottomPoints.push(module)
}
if (isRightExposedHalfTop) {
leftExposedHalfTopModules.push(module)
}
if (isLeftExposedHalfTop) {
rightExposedHalfTopPoints.push(module)
}
})
// 4개중 한개라도 있는 경우 치조배치로 간주한다.
const isChidory =
leftExposedHalfBottomModules.length > 0 ||
rightExposedHalfBottomPoints.length > 0 ||
leftExposedHalfTopModules.length > 0 ||
rightExposedHalfTopPoints.length > 0
surface.isChidory = isChidory
if (plvrYn === 'N' && isChidory) {
swalFire({ text: '치조불가공법입니다.', icon: 'error' })
clear()
throw new Error('치조불가공법입니다.')
}
surface.set({ isChidory: isChidory })
canvas
.getObjects()
.filter((obj) => ['eaveBar', 'halfEaveBar'].includes(obj.name) && obj.parentId === surface.id)
.forEach((obj) => {
canvas.remove(obj)
})
if (isEaveBar) {
// 처마력바설치 true인 경우 설치
exposedBottomModules.forEach((module) => {
const bottomPoints = findTopTwoPoints([...module.getCurrentPoints()], direction)
if (!bottomPoints) return
const eaveBar = new fabric.Line([bottomPoints[0].x, bottomPoints[0].y, bottomPoints[1].x, bottomPoints[1].y], {
parent: surface,
name: TRESTLE_MATERIAL.EAVE_BAR,
stroke: 'blue',
strokeWidth: 4,
selectable: false,
surfaceId: surface.id,
parentId: module.id,
visible: isTrestleDisplay,
})
canvas.add(eaveBar)
canvas.renderAll()
})
if (isChidory && cvrPlvrYn === 'Y') {
leftExposedHalfBottomModules.forEach((module) => {
const bottomPoints = findTopTwoPoints([...module.getCurrentPoints()], direction)
let barPoints = []
//설치해야할 반처마커버 포인트를 방향에 따라 설정
if (direction === 'south') {
barPoints = [bottomPoints[0].x, bottomPoints[0].y, bottomPoints[1].x - module.width / 2, bottomPoints[1].y]
} else if (direction === 'north') {
barPoints = [bottomPoints[0].x + module.width / 2, bottomPoints[0].y, bottomPoints[1].x, bottomPoints[1].y]
} else if (direction === 'east') {
barPoints = [bottomPoints[0].x, bottomPoints[0].y, bottomPoints[1].x, bottomPoints[0].y - module.height / 2]
} else if (direction === 'west') {
barPoints = [bottomPoints[0].x, bottomPoints[0].y, bottomPoints[1].x, bottomPoints[1].y - module.height / 2]
}
if (!bottomPoints) return
const halfEaveBar = new fabric.Line(barPoints, {
parent: surface,
name: TRESTLE_MATERIAL.HALF_EAVE_BAR,
stroke: 'blue',
strokeWidth: 4,
selectable: false,
surfaceId: surface.id,
parentId: module.id,
visible: isTrestleDisplay,
})
canvas.add(halfEaveBar)
canvas.renderAll()
})
rightExposedHalfBottomPoints.forEach((module) => {
const bottomPoints = findTopTwoPoints([...module.points], direction)
let barPoints = []
//설치해야할 반처마커버 포인트를 방향에 따라 설정
if (direction === 'south') {
barPoints = [bottomPoints[0].x + module.width / 2, bottomPoints[0].y, bottomPoints[1].x, bottomPoints[1].y]
} else if (direction === 'north') {
barPoints = [bottomPoints[0].x, bottomPoints[0].y, bottomPoints[0].x + module.width / 2, bottomPoints[1].y]
} else if (direction === 'east') {
barPoints = [bottomPoints[0].x, bottomPoints[1].y + module.height / 2, bottomPoints[1].x, bottomPoints[1].y]
} else if (direction === 'west') {
barPoints = [bottomPoints[0].x, bottomPoints[1].y - module.height / 2, bottomPoints[1].x, bottomPoints[1].y]
}
if (!bottomPoints) return
const halfEaveBar = new fabric.Line(barPoints, {
parent: surface,
name: TRESTLE_MATERIAL.HALF_EAVE_BAR,
stroke: 'blue',
strokeWidth: 4,
selectable: false,
parentId: module.id,
visible: isTrestleDisplay,
})
canvas.add(halfEaveBar)
canvas.renderAll()
})
}
}
const horizontal = ['south', 'north'].includes(direction) ? surface.trestleDetail.moduleIntvlHor : surface.trestleDetail.moduleIntvlVer
const vertical = ['south', 'north'].includes(direction) ? surface.trestleDetail.moduleIntvlVer : surface.trestleDetail.moduleIntvlHor
let mostRowsModule = 0 // 모듈 최대 단 수
// 가대 설치를 위한 가장 아래 모듈로부터 위로 몇단인지 계산
// 오른쪽,왼쪽 둘 다 아래에 아무것도 없는, 처마 커버를 필요로 하는 모듈
exposedBottomModules.forEach((module) => {
let { width, height } = { ...module }
width = Math.floor(width)
height = Math.floor(height)
let { x: startX, y: startY } = { ...module.getCenterPoint() }
let { x, y } = { ...module.getCenterPoint() }
let leftRows = 1
let rightRows = 1
let centerRows = 1
let hasNextModule = true
let findLeft = true
let findRight = true
let leftFindModuleList = [module]
let rightFindModuleList = [module]
let centerFindModuleList = [module]
//우선 절반을 나눈 뒤 왼쪽부터 찾는다.
while (hasNextModule) {
//바로 위에 있는지 확인한다.
let nextModule = findNextModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
if (nextModule) {
// 바로 위 모듈을 찾는다.
leftRows++
leftFindModuleList.push(nextModule)
x = nextModule.x
y = nextModule.y
} else {
// 바로 위가 없을 경우 먼저 왼쪽위가 있는지 확인 한다.
if (findLeft) {
nextModule = findNextLeftModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findLeft = false
} else {
nextModule = findNextRightModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findLeft = true
}
if (nextModule) {
// 바로 위 모듈을 찾는다.
leftRows++
leftFindModuleList.push(nextModule)
x = nextModule.x
y = nextModule.y
} else {
hasNextModule = false
}
}
}
hasNextModule = true
x = startX
y = startY
// 오른쪽 찾는다.
while (hasNextModule) {
//바로 위에 있는지 확인한다.
let nextModule = findNextModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
if (nextModule) {
// 바로 위 모듈을 찾는다.
rightRows++
rightFindModuleList.push(nextModule)
x = nextModule.x
y = nextModule.y
} else {
// 바로 위가 없을 경우 먼저 왼쪽위가 있는지 확인 한다.
if (findRight) {
nextModule = findNextRightModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findRight = false
} else {
nextModule = findNextLeftModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findRight = true
}
if (nextModule) {
// 바로 위 모듈을 찾는다.
rightRows++
rightFindModuleList.push(nextModule)
x = nextModule.x
y = nextModule.y
} else {
hasNextModule = false
}
}
}
hasNextModule = true
x = startX
y = startY
// 센터 찾는다.
while (hasNextModule) {
//바로 위에 있는지 확인한다.
let nextModule = findNextModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
if (nextModule) {
// 바로 위 모듈을 찾는다.
centerFindModuleList.push(nextModule)
centerRows++
x = nextModule.x
y = nextModule.y
} else {
hasNextModule = false
}
}
const leftModuleInfos = leftFindModuleList.map((module) => {
return {
moduleTpCd: module.moduleInfo.moduleTpCd,
}
})
const rightModuleInfos = rightFindModuleList.map((module) => {
return {
moduleTpCd: module.moduleInfo.moduleTpCd,
}
})
const centerModuleInfos = centerFindModuleList.map((module) => {
return {
moduleTpCd: module.moduleInfo.moduleTpCd,
}
})
const leftRowsInfo = moduleTransformData(leftModuleInfos)
const rightRowsInfo = moduleTransformData(rightModuleInfos)
const centerRowsInfo = moduleTransformData(centerModuleInfos)
// 모듈의 왼쪽 부터 그릴 랙 정보를 가져온다.
const leftRacks = rackInfos.find((rack) => {
if (leftRowsInfo.rowsInfo.length === 1) {
return (
rack.value.moduleTpCd === leftRowsInfo.moduleTotalTp &&
rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
)
} else {
return (
rack.value.moduleTpCd === leftRowsInfo.moduleTotalTp &&
rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
Number(rack.value.moduleTpRows1) === leftRowsInfo.rowsInfo[0].count &&
Number(rack.value.moduleTpRows2) === leftRowsInfo.rowsInfo[1].count
)
}
})?.value.racks
// 모듈의 오른쪽 부터 그릴 랙 정보를 가져온다.
const rightRacks = rackInfos.find((rack) => {
if (rightRowsInfo.rowsInfo.length === 1) {
return (
rack.value.moduleTpCd === rightRowsInfo.moduleTotalTp &&
rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
)
} else {
return (
rack.value.moduleTpCd === rightRowsInfo.moduleTotalTp &&
rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
Number(rack.value.moduleTpRows1) === rightRowsInfo.rowsInfo[0].count &&
Number(rack.value.moduleTpRows2) === rightRowsInfo.rowsInfo[1].count
)
}
})?.value.racks
// 해당 rack으로 그려준다.
const centerRacks = rackInfos.find((rack) => {
if (centerRowsInfo.rowsInfo.length === 1) {
return (
rack.value.moduleTpCd === centerRowsInfo.moduleTotalTp &&
rack.value.moduleRows === centerRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
)
} else {
return (
rack.value.moduleTpCd === centerRowsInfo.moduleTotalTp &&
rack.value.moduleRows === centerRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
Number(rack.value.moduleTpRows1) === centerRowsInfo.rowsInfo[0].count &&
Number(rack.value.moduleTpRows2) === centerRowsInfo.rowsInfo[1].count
)
}
})?.value.racks
mostRowsModule = Math.max(leftRows, rightRows, centerRows, mostRowsModule)
if (rackYn === 'Y') {
drawRacks(leftRacks, rackQty, rackIntvlPct, module, direction, 'L', rackYn)
drawRacks(rightRacks, rackQty, rackIntvlPct, module, direction, 'R', rackYn)
if (rackQty === 3) {
//rack 갯수가 3개인 경우는 중간렉도 추가해줘야함
drawRacks(centerRacks, rackQty, rackIntvlPct, module, direction, 'C', rackYn)
} else if (rackQty === 4) {
drawRacks(leftRacks, rackQty, rackIntvlPct / 3, module, direction, 'L', rackYn)
drawRacks(rightRacks, rackQty, rackIntvlPct / 3, module, direction, 'R', rackYn)
}
}
module.set({ leftRows, rightRows, centerRows })
})
// 왼쪽아래에 모듈이 없는 모듈들
leftExposedHalfBottomModules.forEach((module) => {
const { width, height } = module
let { x: startX, y: startY } = { ...module.getCenterPoint() }
let { x, y } = { ...module.getCenterPoint() }
let leftRows = 1
let hasNextModule = true
let findLeft = true
let findModuleList = [module]
//우선 절반을 나눈 뒤 왼쪽부터 찾는다.
while (hasNextModule) {
//바로 위에 있는지 확인한다.
let nextModule = findNextModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
if (nextModule) {
// 바로 위 모듈을 찾는다.
leftRows++
findModuleList.push(nextModule)
x = nextModule.x
y = nextModule.y
} else {
// 바로 위가 없을 경우 먼저 왼쪽위가 있는지 확인 한다.
if (findLeft) {
nextModule = findNextLeftModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findLeft = false
} else {
nextModule = nextModule = findNextRightModule(
{
x,
y,
width,
height,
horizontal,
vertical,
},
centerPoints,
direction,
)
findLeft = true
}
if (nextModule) {
// 바로 위 모듈을 찾는다.
leftRows++
findModuleList.push(nextModule)
x = nextModule.x
y = nextModule.y
} else {
hasNextModule = false
}
}
}
const leftModuleInfos = findModuleList.map((module) => {
return {
moduleTpCd: module.moduleInfo.moduleTpCd,
}
})
const leftRowsInfo = moduleTransformData(leftModuleInfos)
// 모듈의 왼쪽 부터 그릴 랙 정보를 가져온다.
const leftRacks = rackInfos.find((rack) => {
if (leftRowsInfo.rowsInfo.length === 1) {
return (
rack.value.moduleTpCd === leftRowsInfo.moduleTotalTp &&
rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
)
} else {
return (
rack.value.moduleTpCd === leftRowsInfo.moduleTotalTp &&
rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
Number(rack.value.moduleTpRows1) === leftRowsInfo.rowsInfo[0].count &&
Number(rack.value.moduleTpRows2) === leftRowsInfo.rowsInfo[1].count
)
}
})?.value.racks
mostRowsModule = Math.max(leftRows, mostRowsModule)
if (rackYn === 'Y') {
drawRacks(leftRacks, rackQty, rackIntvlPct, module, direction, 'L', rackYn)
}
module.set({ leftRows })
})
// 오른쪽 아래에 모듈이 없는 모듈들
rightExposedHalfBottomPoints.forEach((module) => {
const { width, height } = module
let { x: startX, y: startY } = { ...module.getCenterPoint() }
let { x, y } = { ...module.getCenterPoint() }
let rightRows = 1
let hasNextModule = true
let findRight = true
let findModuleList = [module]
// 오른쪽 찾는다.
while (hasNextModule) {
//바로 위에 있는지 확인한다.
let nextModule = findNextModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
if (nextModule) {
// 바로 위 모듈을 찾는다.
rightRows++
findModuleList.push(nextModule)
x = nextModule.x
y = nextModule.y
} else {
// 바로 위가 없을 경우 먼저 왼쪽위가 있는지 확인 한다.
if (findRight) {
nextModule = findNextRightModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findRight = false
} else {
nextModule = findNextLeftModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findRight = true
}
if (nextModule) {
// 바로 위 모듈을 찾는다.
rightRows++
findModuleList.push(nextModule)
x = nextModule.x
y = nextModule.y
} else {
hasNextModule = false
}
}
}
const rightRowsInfos = findModuleList.map((module) => {
return {
moduleTpCd: module.moduleInfo.moduleTpCd,
}
})
const rightRowsInfo = moduleTransformData(rightRowsInfos)
// 모듈의 오른쪽 부터 그릴 랙 정보를 가져온다.
const rightRacks = rackInfos.find((rack) => {
if (rightRowsInfo.rowsInfo.length === 1) {
return (
rack.value.moduleTpCd === rightRowsInfo.moduleTotalTp &&
rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
)
} else {
return (
rack.value.moduleTpCd === rightRowsInfo.moduleTotalTp &&
rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
Number(rack.value.moduleTpRows1) === rightRowsInfo.rowsInfo[0].count &&
Number(rack.value.moduleTpRows2) === rightRowsInfo.rowsInfo[1].count
)
}
})?.value.racks
mostRowsModule = Math.max(rightRows, mostRowsModule)
// 해당 rack으로 그려준다.
if (rackYn === 'Y') {
drawRacks(rightRacks, rackQty, rackIntvlPct, module, direction, 'R', rackYn)
}
module.set({ rightRows })
})
surface.set({ moduleRowsTotCnt: mostRowsModule })
if (rackYn === 'N') {
// rack이 없을경우
installBracketWithOutRack(surface, exposedBottomModules, leftExposedHalfBottomModules, rightExposedHalfBottomPoints, isChidory)
} else if (rackYn === 'Y') {
installBracket(surface)
}
const quotationParam = getTrestleParams(surface, exposedBottomModules)
surface.set({ quotationParam })
})
return true
} catch (e) {
// 에러 발생시 가대 초기화
console.error(e)
clear()
setViewCircuitNumberTexts(true)
setIsGlobalLoading(false)
return false
}
}
//module Rack 정보를 얻기위한 데이터 가공
function moduleTransformData(arr) {
let counts = {}
arr.forEach((item) => {
counts[item.moduleTpCd] = (counts[item.moduleTpCd] || 0) + 1
})
let moduleTotalTp = Object.keys(counts).join('')
let rowsInfo = Object.entries(counts).map(([moduleTpCd, count]) => ({ moduleTpCd, count }))
return { moduleTotalTp, rowsInfo }
}
// itemList 조회 후 estimateParam에 저장
const getEstimateData = async () => {
const surfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
//surfaces.pcses들을 배열로 묶는다
const pcses = surfaces[0].pcses.filter((pcs) => pcs !== null && pcs !== undefined)
surfaces.forEach((surface, index) => {
if (index !== 0) {
if (surface.pcses) {
pcses.concat(surface.pcses)
}
}
})
const allModules = surfaces.map((surface) => surface.modules).flat()
// 모듈 파라미터 생성
const modules = getModulesParam(allModules)
const trestles = []
//가대 파라미터 생성
surfaces.forEach((surface) => {
if (surface.quotationParam) {
trestles.push(surface.quotationParam)
}
})
// trestles 배열에서 null인 경우 제거
const params = { trestles, pcses, modules }
//견적서 itemList 조회
const { data, data2, result } = await getQuotationItem(params)
if (result.resultCode === 'E') {
swalFire({ text: result.resultMsg, icon: 'error' })
return
}
let itemList
if (!data || data.length === 0) {
return
}
itemList = data
//northArrangement 북면 설치 여부
const northArrangement = getNorthArrangement()
// circuitItemList의 경우는 moduleList에서 circuitId만 groupBy한다.
let circuitItemList = []
// roofSurfaceList 생성
const roofSurfaceList = surfaces.map((surface) => {
const parent = canvas.getObjects().find((obj) => obj.id === surface.parentId)
const { directionText, roofMaterial, moduleCompass, surfaceCompass } = parent
const slope = Number(roofMaterial.pitch)
const roofMaterialIndex = parent.roofMaterial.index
const { nameJp: roofMaterialIdMulti } = roofMaterial
const moduleSelection = moduleSelectionData?.roofConstructions?.find((construction) => construction.roofIndex === roofMaterialIndex)
let construction = moduleSelection?.construction
let constructSpecification = +roofSizeSet === 3 ? null : construction.constTp
let constructSpecificationMulti = +roofSizeSet === 3 ? null : construction.constTpJp
const trestle = moduleSelection?.trestle
let trestleMkrCd = +roofSizeSet === 3 ? null : trestle.trestleMkrCd
let supportMethodId = +roofSizeSet === 3 ? null : trestle.constMthdCd
let roofBaseCd = +roofSizeSet === 3 ? null : trestle.roofBaseCd
let supportMeaker = +roofSizeSet === 3 ? null : trestle.trestleMkrCdJp
let supportMethodIdMulti = +roofSizeSet === 3 ? null : trestle.constMthdCdJp
const modules = surface.modules
const moduleList = modules.map((module) => {
circuitItemList.push(module.pcsItemId)
return {
itemId: module.moduleInfo.itemId,
circuit: module.circuitNumber,
pcItemId: module.pcsItemId,
}
})
return {
roofSurfaceId: surface.id,
roofSurface: directionText.replace(/[0-9]/g, ''),
roofMaterialId: +roofSizeSet === 3 ? '陸屋根' : roofMaterial.roofMatlCd, // 육지붕의 경우 지붕재 ID 값이 없기 때문에 임의 값 지정
supportMethodId,
constructSpecification,
constructSpecificationMulti,
roofMaterialIdMulti: +roofSizeSet === 3 ? '陸屋根' : roofMaterialIdMulti,
supportMethodIdMulti,
supportMeaker,
slope: +roofSizeSet === 3 ? 0 : slope,
classType: currentAngleType === 'slope' ? '0' : '1',
angle: +roofSizeSet === 3 ? 0 : getDegreeByChon(slope),
azimuth: getAzimuth(parent),
moduleList,
}
})
// circuitItemList 중복제거
circuitItemList = circuitItemList.filter((item, index) => circuitItemList.indexOf(item) === index)
circuitItemList = getSelectedPcsItemList()
return { itemList, northArrangement, roofSurfaceList, circuitItemList }
}
// 발전 시뮬레이션 용 각도 재계산
const getAzimuth = (parent) => {
const { moduleCompass, surfaceCompass, direction } = parent
if (surfaceCompass) {
if (surfaceCompass > 180) {
return surfaceCompass - 360
}
return surfaceCompass
}
switch (direction) {
case 'south': {
if (moduleCompass < 0) {
return -1 * moduleCompass
} else if (moduleCompass === 0) {
return 0
} else if (moduleCompass < 180) {
return -1 * moduleCompass
} else if (moduleCompass === 180) {
return 180
}
}
case 'north': {
if (moduleCompass < 0) {
return -1 * (180 + moduleCompass)
} else if (moduleCompass === 0) {
return 180
} else if (moduleCompass < 180) {
return 180 - moduleCompass
} else if (moduleCompass === 180) {
return 0
}
}
case 'west': {
if (moduleCompass > -180 && moduleCompass < -90) {
return -180 - (90 + moduleCompass)
} else if (moduleCompass < 0) {
return 180 - (90 + moduleCompass)
} else if (moduleCompass === 0) {
return 90
} else if (moduleCompass < 180) {
return 90 - moduleCompass
} else if (moduleCompass === 180) {
return -90
}
}
case 'east': {
if (moduleCompass < 0) {
return -(90 + moduleCompass)
} else if (moduleCompass === 0) {
return -90
} else if (moduleCompass < 90) {
return -180 + (90 - moduleCompass)
} else if (moduleCompass < 180) {
return 180 + (90 - moduleCompass)
} else if (moduleCompass === 180) {
return 90
}
}
}
return 0
}
// 북면설치가 한개라도 되어있는지 확인
const getNorthArrangement = () => {
const surfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
let northArrangement = '0'
surfaces.forEach((surface) => {
const parent = canvas.getObjects().find((obj) => obj.id === surface.parentId)
const directionText = parent.directionText
// ['西北西','東北東'] 의 경우를 제외하고는 北이 들어간 경우 전부 북면으로 간주
if (directionText.includes('北') && !directionText.includes('西北西') && !directionText.includes('東北東')) {
if (surface.modules.length > 0) {
northArrangement = '1'
}
}
})
return northArrangement
}
// 다음 윗 모듈을 찾는다.
const findNextModule = (currentPoint, centerPoints, direction) => {
let { x, y, horizontal, vertical } = { ...currentPoint }
let { widthArr, heightArr } = centerPoints[0]
let width = widthArr.reduce((acc, num) => acc + num, 0) / widthArr.length + horizontal
let height = heightArr.reduce((acc, num) => acc + num, 0) / heightArr.length + vertical
let maxX = MODULE_MARGIN
let maxY = MODULE_MARGIN
let result
switch (direction) {
case 'south': {
heightArr.forEach((height) => {
if (result) return
result = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y - height)) < maxY)
})
break
}
case 'north': {
heightArr.forEach((height) => {
if (result) return
result = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y + height)) < maxY)
})
break
}
case 'east': {
widthArr.forEach((width) => {
if (result) return
result = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - (x - width)) < maxX && Math.abs(centerPoint.y - y) < maxY)
})
break
}
case 'west': {
widthArr.forEach((width) => {
if (result) return
result = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - (x + width)) < maxX && Math.abs(centerPoint.y - y) < maxY)
})
break
}
}
return result
}
// 다음 왼쪽 모듈을 찾는다.
const findNextLeftModule = (currentPoint, centerPoints, direction) => {
let { x, y, horizontal, vertical } = { ...currentPoint }
let { widthArr, heightArr } = centerPoints[0]
let width = widthArr.reduce((acc, num) => acc + num, 0) / widthArr.length + horizontal
let height = heightArr.reduce((acc, num) => acc + num, 0) / heightArr.length + vertical
let result
let topLeftPoint
let maxX = MODULE_MARGIN
let maxY = MODULE_MARGIN
switch (direction) {
case 'south': {
width = width + horizontal
height = height + vertical
heightArr.forEach((h) => {
topLeftPoint = { x: x - width / 2, y: y - h }
if (result) return
result = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - topLeftPoint.x) < maxX && Math.abs(centerPoint.y - topLeftPoint.y) < maxY,
)
})
break
}
case 'north': {
width = width + horizontal
height = height + vertical
heightArr.forEach((h) => {
topLeftPoint = { x: x + width / 2, y: y + h }
if (result) return
result = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - topLeftPoint.x) < maxX && Math.abs(centerPoint.y - topLeftPoint.y) < maxY,
)
})
break
}
case 'east': {
widthArr.forEach((w) => {
topLeftPoint = { x: x - w, y: y + height / 2 }
if (result) return
result = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - topLeftPoint.x) < maxX && Math.abs(centerPoint.y - topLeftPoint.y) < maxY,
)
})
break
}
case 'west': {
widthArr.forEach((w) => {
topLeftPoint = { x: x + w, y: y - height / 2 }
if (result) return
result = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - topLeftPoint.x) < maxX && Math.abs(centerPoint.y - topLeftPoint.y) < maxY,
)
})
break
}
}
return result
}
// 다음 오른쪽 모듈을 찾는다.
const findNextRightModule = (currentPoint, centerPoints, direction) => {
let { x, y, horizontal, vertical } = { ...currentPoint }
let { widthArr, heightArr } = centerPoints[0]
let width = widthArr.reduce((acc, num) => acc + num, 0) / widthArr.length + horizontal
let height = heightArr.reduce((acc, num) => acc + num, 0) / heightArr.length + vertical
let result
let topRightPoint
let maxX = MODULE_MARGIN
let maxY = MODULE_MARGIN
switch (direction) {
case 'south': {
heightArr.forEach((h) => {
topRightPoint = { x: x + width / 2, y: y - h }
if (result) return
result = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - topRightPoint.x) < maxX && Math.abs(centerPoint.y - topRightPoint.y) < maxY,
)
})
break
}
case 'north': {
heightArr.forEach((h) => {
topRightPoint = { x: x - width / 2, y: y + h }
if (result) return
result = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - topRightPoint.x) < maxX && Math.abs(centerPoint.y - topRightPoint.y) < maxY,
)
})
break
}
case 'east': {
widthArr.forEach((w) => {
topRightPoint = { x: x - w, y: y - height / 2 }
if (result) return
result = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - topRightPoint.x) < maxX && Math.abs(centerPoint.y - topRightPoint.y) < maxY,
)
})
break
}
case 'west': {
widthArr.forEach((w) => {
topRightPoint = { x: x + w, y: y + height / 2 }
if (result) return
result = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - topRightPoint.x) < maxX && Math.abs(centerPoint.y - topRightPoint.y) < maxY,
)
})
break
}
}
return result
}
// rack을 그린다.
const drawRacks = (rackInfos, rackQty, rackIntvlPct, module, direction, l, rackYn) => {
const { width, height, left, top, lastX, lastY, surfaceId } = module
const surface = canvas.getObjects().find((obj) => obj.id === surfaceId)
if (!rackInfos) {
const maxRows = surface.trestleDetail.moduleMaxRows
const maxCols = surface.trestleDetail.moduleMaxCols
const msg = `選択した家で設置可能
モジュールの最大段数は${maxRows}、最大列数は${maxCols}です。
上限より上部に取り付けたモジュールを削除してください。`
swalFire({ title: msg, type: 'alert' })
throw new Error('rackInfos is null')
}
const roof = canvas.getObjects().find((obj) => obj.id === surface.parentId)
const degree = getDegreeByChon(roof.roofMaterial.pitch)
const moduleLeft = lastX ?? left
const moduleTop = lastY ?? top
let startPointX, startPointY
switch (l) {
case 'L': {
// 왼쪽부분 시작 점
if (direction === 'south') {
startPointX = module.left + width / rackIntvlPct
startPointY = module.top + module.height
break
} else if (direction === 'east') {
startPointX = module.left + width
startPointY = module.top + height - height / rackIntvlPct
break
} else if (direction === 'west') {
startPointX = module.left
startPointY = module.top + height / rackIntvlPct
break
} else if (direction === 'north') {
startPointX = module.left + width - width / rackIntvlPct
startPointY = module.top
break
}
}
case 'R': {
// 오른쪽부분 시작 점
if (direction === 'south') {
startPointX = module.left + module.width - width / rackIntvlPct
startPointY = module.top + module.height / 2 + height / 2
break
} else if (direction === 'east') {
startPointX = module.left + width
startPointY = module.top + height / rackIntvlPct
break
} else if (direction === 'west') {
startPointX = module.left
startPointY = module.top + height - height / rackIntvlPct
break
} else if (direction === 'north') {
startPointX = module.left + width / rackIntvlPct
startPointY = module.top
break
}
}
case 'C': {
// 중간부분 시작점
if (direction === 'south') {
const x = module.left + module.width / 2
const y = module.top + module.height / 2
startPointX = x
startPointY = y + height / 2
break
} else if (direction === 'east') {
const x = module.left + width
const y = module.top + module.height / 2
startPointX = x
startPointY = y
break
} else if (direction === 'west') {
const x = module.left
const y = module.top + module.height / 2
startPointX = x
startPointY = y
break
} else if (direction === 'north') {
const x = module.left + module.width / 2
const y = module.top
startPointX = x
startPointY = y
break
}
}
}
switch (direction) {
case 'south': {
rackInfos.forEach((rackInfo) => {
const { rackLen, itemId, supFitQty, supFitIntvlPct, rackRowsCd, smartRack, smartRackYn } = rackInfo
let rackLength = getTrestleLength(rackLen, degree) / 10
if (smartRackYn === 'Y') {
let smartRackId = uuidv4()
smartRack.forEach(({ seq, setRackTpCd, setRackTpLen, supFitQty }) => {
rackLength = getTrestleLength(setRackTpLen, degree) / 10
if (setRackTpCd === 'RACK') {
const rack = new fabric.Line([startPointX, startPointY, startPointX, startPointY - rackLength], {
name: TRESTLE_MATERIAL.SMART_RACK,
stroke: 'red',
strokeWidth: 4,
selectable: true,
shadow: {
color: 'black', // Outline color
blur: 10,
offsetX: 0,
offsetY: 0,
},
visible: isTrestleDisplay,
parentId: module.id,
surfaceId: surface.id,
supFitQty,
supFitIntvlPct,
rackLen: rackLength,
rackRowsCd,
seq,
smartRackId,
rackId: itemId,
direction: 'top',
})
startPointY -= rackLength + 8
canvas.add(rack)
canvas.renderAll()
} else if (setRackTpCd === 'INTVL') {
startPointY -= rackLength
}
})
} else {
const rack = new fabric.Line([startPointX, startPointY, startPointX, startPointY - rackLength], {
name: TRESTLE_MATERIAL.RACK,
stroke: 'red',
strokeWidth: 4,
selectable: false,
fill: 'red',
shadow: {
color: 'black', // Outline color
blur: 10,
offsetX: 0,
offsetY: 0,
},
parentId: module.id,
surfaceId: surface.id,
visible: isTrestleDisplay,
supFitQty,
supFitIntvlPct,
rackLen,
rackRowsCd,
rackId: itemId,
direction: 'top',
})
canvas.add(rack)
canvas.renderAll()
}
startPointY -= rackLength + 8
})
break
}
case 'east': {
rackInfos.forEach((rackInfo) => {
const { rackLen, itemId, supFitQty, supFitIntvlPct, rackRowsCd, smartRack, smartRackYn } = rackInfo
let rackLength = getTrestleLength(rackLen, degree) / 10
if (smartRackYn === 'Y') {
let smartRackId = uuidv4()
smartRack.forEach(({ seq, setRackTpCd, setRackTpLen, supFitQty }) => {
rackLength = getTrestleLength(setRackTpLen, degree) / 10
if (setRackTpCd === 'RACK') {
const rack = new fabric.Line([startPointX, startPointY, startPointX - rackLength, startPointY], {
name: TRESTLE_MATERIAL.SMART_RACK,
stroke: 'red',
strokeWidth: 4,
selectable: false,
shadow: {
color: 'black', // Outline color
blur: 10,
offsetX: 0,
offsetY: 0,
},
parentId: module.id,
surfaceId: surface.id,
visible: isTrestleDisplay,
supFitQty,
supFitIntvlPct,
rackLen: rackLength,
rackRowsCd,
seq,
smartRackId,
rackId: itemId,
direction: 'left',
})
startPointX -= rackLength + 8
canvas.add(rack)
canvas.renderAll()
} else if (setRackTpCd === 'INTVL') {
startPointX -= rackLength
}
})
} else {
const rack = new fabric.Line([startPointX, startPointY, startPointX - rackLength, startPointY], {
name: TRESTLE_MATERIAL.RACK,
stroke: 'red',
shadow: {
color: 'black', // Outline color
blur: 10,
offsetX: 0,
offsetY: 0,
},
parentId: module.id,
surfaceId: surface.id,
strokeWidth: 4,
selectable: false,
visible: isTrestleDisplay,
supFitQty,
supFitIntvlPct,
rackLen,
rackYn,
rackRowsCd,
rackId: itemId,
direction: 'left',
})
canvas.add(rack)
canvas.renderAll()
}
startPointX -= rackLength + 8
})
break
}
case 'west': {
rackInfos.forEach((rackInfo) => {
const { rackLen, itemId, supFitQty, supFitIntvlPct, rackRowsCd, smartRack, smartRackYn } = rackInfo
let rackLength = getTrestleLength(rackLen, degree) / 10
if (smartRackYn === 'Y') {
let smartRackId = uuidv4()
smartRack.forEach(({ seq, setRackTpCd, setRackTpLen, supFitQty }) => {
rackLength = getTrestleLength(setRackTpLen, degree) / 10
if (setRackTpCd === 'RACK') {
const rack = new fabric.Line([startPointX, startPointY, startPointX + rackLength, startPointY], {
name: TRESTLE_MATERIAL.SMART_RACK,
stroke: 'red',
strokeWidth: 4,
selectable: false,
shadow: {
color: 'black', // Outline color
blur: 10,
offsetX: 0,
offsetY: 0,
},
parentId: module.id,
surfaceId: surface.id,
visible: isTrestleDisplay,
supFitQty,
supFitIntvlPct,
rackLen: rackLength,
rackRowsCd,
seq,
smartRackId,
rackId: itemId,
direction: 'right',
})
startPointX += rackLength + 8
canvas.add(rack)
canvas.renderAll()
} else if (setRackTpCd === 'INTVL') {
startPointX += rackLength
}
})
} else {
const rack = new fabric.Line([startPointX, startPointY, startPointX + rackLength, startPointY], {
name: TRESTLE_MATERIAL.RACK,
stroke: 'red',
shadow: {
color: 'black', // Outline color
blur: 10,
offsetX: 0,
offsetY: 0,
},
parentId: module.id,
surfaceId: surface.id,
visible: isTrestleDisplay,
strokeWidth: 4,
selectable: false,
supFitQty,
supFitIntvlPct,
rackLen,
rackRowsCd,
rackId: itemId,
direction: 'right',
})
canvas.add(rack)
canvas.renderAll()
}
startPointX += rackLength + 8
})
break
}
case 'north': {
rackInfos.forEach((rackInfo) => {
const { rackLen, itemId, supFitQty, supFitIntvlPct, rackRowsCd, smartRack, smartRackYn } = rackInfo
let rackLength = getTrestleLength(rackLen, degree) / 10
if (smartRackYn === 'Y') {
let smartRackId = uuidv4()
smartRack.forEach(({ seq, setRackTpCd, setRackTpLen, supFitQty }) => {
rackLength = getTrestleLength(setRackTpLen, degree) / 10
if (setRackTpCd === 'RACK') {
const rack = new fabric.Line([startPointX, startPointY, startPointX, startPointY + rackLength], {
name: TRESTLE_MATERIAL.SMART_RACK,
stroke: 'red',
strokeWidth: 4,
selectable: false,
shadow: {
color: 'black', // Outline color
blur: 10,
offsetX: 0,
offsetY: 0,
},
parentId: module.id,
surfaceId: surface.id,
visible: isTrestleDisplay,
supFitQty,
supFitIntvlPct,
rackLen,
rackRowsCd,
seq,
smartRackId,
rackId: itemId,
direction: 'bottom',
})
canvas.add(rack)
canvas.renderAll()
startPointY += rackLength + 8
} else if (setRackTpCd === 'INTVL') {
startPointY += rackLength
}
})
} else {
const rack = new fabric.Line([startPointX, startPointY, startPointX, startPointY + rackLength], {
name: TRESTLE_MATERIAL.RACK,
stroke: 'red',
shadow: {
color: 'black', // Outline color
blur: 10,
offsetX: 0,
offsetY: 0,
},
parentId: module.id,
surfaceId: surface.id,
visible: isTrestleDisplay,
strokeWidth: 4,
selectable: false,
supFitQty,
supFitIntvlPct,
rackLen,
rackRowsCd,
rackId: itemId,
direction: 'bottom',
})
canvas.add(rack)
canvas.renderAll()
}
startPointY += rackLength + 8
})
break
}
}
}
//파라미터로 받은 배치면의 rack을 가지고 지지금구를 그린다.
const installBracket = (surface) => {
const modules = surface.modules
const racks = []
modules.forEach((module) => {
canvas
.getObjects()
.filter((obj) => obj.name === 'rack' || obj.name === 'smartRack')
.forEach((rack) => {
if (rack.parentId === module.id) {
canvas.remove(canvas.getObjects().filter((obj) => obj.name === 'bracket' && obj.parentId === rack.id))
racks.push(rack)
}
})
})
canvas.renderAll()
racks.forEach((rack) => {
let { x1, y1, x2, y2, direction, supFitQty, supFitIntvlPct, rackLen, name } = rack
const bracketLength = 10
if (direction === 'top') {
const result = getBracketPoints(supFitQty, supFitIntvlPct)
result.forEach((percent) => {
const len = name === 'smartRack' ? y2 - (y2 - y1) * percent - bracketLength / 2 : y2 - (y2 - y1) * percent - bracketLength / 2
const bracket = new fabric.Rect({
left: x2 - bracketLength / 3,
top: len,
fill: 'green',
name: TRESTLE_MATERIAL.BRACKET,
parentId: rack.parentId,
visible: isTrestleDisplay,
surfaceId: surface.id,
width: bracketLength,
height: bracketLength,
selectable: false,
})
canvas.add(bracket)
})
canvas.renderAll()
} else if (direction === 'left') {
const result = getBracketPoints(supFitQty, supFitIntvlPct)
result.forEach((percent) => {
const len =
name === 'smartRack' ? x1 - Math.abs(x2 - x1) * percent - bracketLength / 2 : x1 - Math.abs(x2 - x1) * percent - bracketLength / 2
const bracket = new fabric.Rect({
left: len,
top: y2 - bracketLength / 3,
fill: 'green',
name: TRESTLE_MATERIAL.BRACKET,
parentId: rack.parentId,
visible: isTrestleDisplay,
surfaceId: surface.id,
width: bracketLength,
height: bracketLength,
selectable: false,
})
canvas.add(bracket)
})
canvas.renderAll()
} else if (direction === 'right') {
const result = getBracketPoints(supFitQty, supFitIntvlPct)
result.forEach((percent) => {
const len =
name === 'smartRack' ? x2 - Math.abs(x2 - x1) * percent - bracketLength / 2 : x2 - Math.abs(x2 - x1) * percent - bracketLength / 2
const bracket = new fabric.Rect({
left: len,
top: y2 - bracketLength / 3,
fill: 'green',
parentId: rack.parentId,
visible: isTrestleDisplay,
surfaceId: surface.id,
name: TRESTLE_MATERIAL.BRACKET,
width: bracketLength,
height: bracketLength,
selectable: false,
})
canvas.add(bracket)
})
canvas.renderAll()
} else if (direction === 'bottom') {
const result = getBracketPoints(supFitQty, supFitIntvlPct)
result.forEach((percent) => {
const len = name === 'smartRack' ? y2 - (y2 - y1) * percent - bracketLength / 2 : y2 - (y2 - y1) * percent - bracketLength / 2
const bracket = new fabric.Rect({
left: x2 - bracketLength / 3,
top: len,
fill: 'green',
name: TRESTLE_MATERIAL.BRACKET,
parentId: rack.parentId,
visible: isTrestleDisplay,
surfaceId: surface.id,
width: bracketLength,
height: bracketLength,
selectable: false,
})
canvas.add(bracket)
})
canvas.renderAll()
}
})
}
//랙 없음 인 경우 지지금구 설치
const installBracketWithOutRack = (surface, exposedBottomModules, leftExposedHalfBottomModules, rightExposedHalfBottomPoints, isChidory) => {
let { rackQty, rackIntvlPct, moduleIntvlHor, moduleIntvlVer, lessSupFitQty, lessSupFitIntvlPct } = surface.trestleDetail
rackQty = lessSupFitQty
rackIntvlPct = lessSupFitIntvlPct
const direction = surface.direction
canvas.renderAll()
exposedBottomModules.forEach((module) => {
canvas.renderAll()
drawBracketWithOutRack(module, rackIntvlPct, module.leftRows + 1, 'L', surface.direction, moduleIntvlHor, moduleIntvlVer)
drawBracketWithOutRack(module, rackIntvlPct, module.rightRows + 1, 'R', surface.direction, moduleIntvlHor, moduleIntvlVer)
if (!isChidory && rackQty === 3) {
// 치도리가 아니면서 갯수가 3개인 경우 센터도 설치 필요함
drawBracketWithOutRack(module, rackIntvlPct, module.centerRows + 1, 'C', surface.direction, moduleIntvlHor, moduleIntvlVer)
}
if (isChidory && rackQty === 3) {
drawBracketWithOutRack(module, rackIntvlPct / 3, module.leftRows + 1, 'L', surface.direction, moduleIntvlHor, moduleIntvlVer)
}
if (rackQty === 4) {
drawBracketWithOutRack(module, rackIntvlPct / 3, module.leftRows + 1, 'L', surface.direction, moduleIntvlHor, moduleIntvlVer)
drawBracketWithOutRack(module, rackIntvlPct / 3, module.rightRows + 1, 'R', surface.direction, moduleIntvlHor, moduleIntvlVer)
}
if (!isChidory && rackQty === 5) {
drawBracketWithOutRack(module, rackIntvlPct / 3, module.leftRows + 1, 'L', surface.direction, moduleIntvlHor, moduleIntvlVer)
drawBracketWithOutRack(module, rackIntvlPct / 3, module.rightRows + 1, 'R', surface.direction, moduleIntvlHor, moduleIntvlVer)
drawBracketWithOutRack(module, rackIntvlPct / 3, module.rightRows + 1, 'C', surface.direction, moduleIntvlHor, moduleIntvlVer)
}
})
leftExposedHalfBottomModules.forEach((module) => {
drawBracketWithOutRack(module, rackIntvlPct, module.leftRows + 1, 'L', surface.direction, moduleIntvlHor, moduleIntvlVer)
if (rackQty === 3 && !findSamePointInBottom(exposedBottomModules, module)) {
// 해당 모듈과 같은 위치 맨 아래에 모듈이 없는 경우 하나 더 설치 필요
drawBracketWithOutRack(module, rackIntvlPct / 3, module.leftRows + 1, 'L', surface.direction, moduleIntvlHor, moduleIntvlVer)
}
if (rackQty === 4) {
drawBracketWithOutRack(module, rackIntvlPct / 3, module.leftRows + 1, 'L', surface.direction, moduleIntvlHor, moduleIntvlVer)
}
})
rightExposedHalfBottomPoints.forEach((module) => {
drawBracketWithOutRack(module, rackIntvlPct, module.rightRows + 1, 'R', surface.direction, moduleIntvlHor, moduleIntvlVer)
if (rackQty === 3 && !findSamePointInBottom(exposedBottomModules, module, direction)) {
// 해당 모듈과 같은 위치 맨 아래에 모듈이 없는 경우 하나 더 설치 필요
drawBracketWithOutRack(module, rackIntvlPct / 3, module.rightRows + 1, 'R', surface.direction, moduleIntvlHor, moduleIntvlVer)
}
if (rackQty === 4) {
drawBracketWithOutRack(module, rackIntvlPct / 3, module.rightRows + 1, 'R', surface.direction, moduleIntvlHor, moduleIntvlVer)
}
})
}
// 방향에 따라 가장 아래모듈중 같은 좌표가 있는지 확인
const findSamePointInBottom = (exposedBottomModules, module, direction) => {
const { x, y } = module.getCenterPoint()
switch (direction) {
case 'south': {
return exposedBottomModules.find((exposedBottomModule) => {
const { x: exposedX, y: exposedY } = exposedBottomModule.getCenterPoint()
return Math.abs(x - exposedX) < 2 && Math.abs(y - exposedY) > module.height
})
}
case 'north': {
return exposedBottomModules.find((exposedBottomModule) => {
const { x: exposedX, y: exposedY } = exposedBottomModule.getCenterPoint()
return Math.abs(x - exposedX) < 2 && Math.abs(y - exposedY) > module.height
})
}
case 'east': {
return exposedBottomModules.find((exposedBottomModule) => {
const { x: exposedX, y: exposedY } = exposedBottomModule.getCenterPoint()
return Math.abs(y - exposedY) < 2 && Math.abs(x - exposedX) > module.width
})
}
case 'west': {
return exposedBottomModules.find((exposedBottomModule) => {
const { x: exposedX, y: exposedY } = exposedBottomModule.getCenterPoint()
return Math.abs(y - exposedY) < 2 && Math.abs(x - exposedX) > module.width
})
}
}
}
// 랙 없음의 지지금구를 그린다.
const drawBracketWithOutRack = (module, rackIntvlPct, count, l, direction, moduleIntvlHor, moduleIntvlVer) => {
let { width, height, left, top } = module
let startPointX
let startPointY
switch (l) {
case 'L': {
// 왼쪽부분 시작 점
if (direction === 'south') {
startPointX = left + width / rackIntvlPct
startPointY = top + height
break
} else if (direction === 'east') {
startPointX = left + width
startPointY = top + height - height / rackIntvlPct
break
} else if (direction === 'west') {
startPointX = left
startPointY = top + height / rackIntvlPct
break
} else if (direction === 'north') {
startPointX = left + width - width / rackIntvlPct
startPointY = top
break
}
}
case 'R': {
// 오른쪽부분 시작 점
if (direction === 'south') {
startPointX = left + width - width / rackIntvlPct
startPointY = top + height / 2 + height / 2
break
} else if (direction === 'east') {
startPointX = left + width
startPointY = top + height / rackIntvlPct
break
} else if (direction === 'west') {
startPointX = left
startPointY = top + height - height / rackIntvlPct
break
} else if (direction === 'north') {
startPointX = left + width / rackIntvlPct
startPointY = top
break
}
}
case 'C': {
// 중간부분 시작점
if (direction === 'south') {
const x = left + width / 2
const y = top + height / 2
startPointX = x
startPointY = y + height / 2
break
} else if (direction === 'east') {
const x = left + width
const y = top + height / 2
startPointX = x
startPointY = y
break
} else if (direction === 'west') {
const x = left
const y = top + height / 2
startPointX = x
startPointY = y
break
} else if (direction === 'north') {
const x = left + width / 2
const y = top
startPointX = x
startPointY = y
break
}
}
}
for (let i = 0; i < count; i++) {
const bracket = new fabric.Rect({
left: startPointX - 5,
top: startPointY - 5,
fill: 'green',
name: TRESTLE_MATERIAL.BRACKET,
parentId: module.id,
surfaceId: module.surfaceId,
width: 10,
height: 10,
selectable: false,
visible: isTrestleDisplay,
})
canvas.add(bracket)
canvas.renderAll()
if (direction === 'south') {
startPointY -= height
} else if (direction === 'north') {
startPointY += height
} else if (direction === 'east') {
startPointX -= width
} else if (direction === 'west') {
startPointX += width
}
}
}
const getBracketPoints = (n, percent) => {
if (n < 2) {
return []
}
const points = []
const topY = percent / 100 // 맨 위의 점의 y 좌표 (10%)
const bottomY = 1 - percent / 100 // 맨 아래의 점의 y 좌표 (90%)
// 맨 위의 점 추가
points.push(topY)
// 중간 점들 추가
const interval = (bottomY - topY) / (n - 1)
for (let i = 1; i < n - 1; i++) {
points.push(topY + i * interval)
}
// 맨 아래의 점 추가
points.push(bottomY)
return points
}
function findTopTwoPoints(points, direction) {
switch (direction) {
case 'south':
points.sort((a, b) => b.y - a.y)
break
case 'north':
points.sort((a, b) => a.y - b.y)
break
case 'east':
points.sort((a, b) => b.x - a.x)
break
case 'west':
points.sort((a, b) => a.x - b.x)
break
}
return points.slice(0, 2)
}
const getCenterPoints = (moduleSurface) => {
const centerPoints = []
let widthArr = []
let heightArr = []
const modules = moduleSurface.modules
modules.forEach((module, index) => {
module.tempIndex = index
const { x, y } = module.getCenterPoint()
const { width, height } = { ...module }
widthArr.push(width)
heightArr.push(height)
centerPoints.push({ x, y, width: Math.floor(width), height: Math.floor(height), index, moduleInfo: module.moduleInfo })
})
//widthArr 중복 제거 1이상 차이가 나지 않으면 같은 너비로 간주
widthArr = removeCloseValues(Array.from(new Set(widthArr)))
heightArr = removeCloseValues(Array.from(new Set(heightArr)))
const widthAvg = widthArr.reduce((acc, num) => acc + num, 0) / widthArr.length
const heightAvg = heightArr.reduce((acc, num) => acc + num, 0) / heightArr.length
widthArr.push(widthAvg)
heightArr.push(heightAvg)
centerPoints.forEach((centerPoint, index) => {
// widthArr의 평균값을 추가한다.
centerPoint.widthArr = [...widthArr]
centerPoint.heightArr = [...heightArr]
})
function removeCloseValues(arr, threshold = 1) {
arr.sort((a, b) => a - b) // 배열을 정렬
let result = []
for (let i = 0; i < arr.length; i++) {
if (i === 0 || Math.abs(arr[i] - arr[i - 1]) >= threshold) {
result.push(arr[i])
}
}
return result
}
return centerPoints
}
const calculateForApi = (moduleSurface) => {
const centerPoints = getCenterPoints(moduleSurface)
const direction = moduleSurface.direction
const modules = moduleSurface.modules
const horizontal = ['south', 'north'].includes(direction)
? moduleSurface.trestleDetail.moduleIntvlHor
: moduleSurface.trestleDetail.moduleIntvlVer
const vertical = ['south', 'north'].includes(direction) ? moduleSurface.trestleDetail.moduleIntvlVer : moduleSurface.trestleDetail.moduleIntvlHor
const maxX = MODULE_MARGIN
const maxY = MODULE_MARGIN
if (centerPoints.length === 0) return
//완전 노출 하면
let exposedBottom = 0
// 반 노출 하면
let exposedHalfBottom = 0
// 완전 노출 상면
let exposedTop = 0
//반 노출 상면
let exposedHalfTop = 0
// 완전 접면
let touchDimension = 0
//반접면
let halfTouchDimension = 0
// 노출bottom면의 points
let exposedBottomPoints = []
// 반노출 bottom면의 points
let leftExposedHalfBottomPoints = []
let rightExposedHalfBottomPoints = []
let leftExposedHalfTopPoints = []
let rightExposedHalfTopPoints = []
centerPoints.forEach((centerPoint, index) => {
let { x, y, width, height, widthArr, heightArr } = { ...centerPoint }
// centerPoints중에 현재 centerPoint와 x값이 같고, y값이 y-height값과 같은 centerPoint가 있는지 확인
let bottomCell
let bottomLeftPoint
let bottomRightPoint
let leftBottomCnt = 0
let rightBottomCnt = 0
switch (direction) {
case 'south':
//widthArr의 값을 전부 더한 후 widthArr의 길이로 나누어 평균값을 구한다.
width = widthArr.reduce((acc, num) => acc + num, 0) / widthArr.length + horizontal
height = heightArr.reduce((acc, num) => acc + num, 0) / heightArr.length + vertical
heightArr.forEach((h) => {
if (bottomCell) return
bottomCell = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y + h)) < maxY)
if (leftBottomCnt === 0) {
bottomLeftPoint = { x: x - width / 2, y: y + h }
leftBottomCnt = centerPoints.filter(
(centerPoint) => Math.abs(centerPoint.x - bottomLeftPoint.x) < maxX && Math.abs(centerPoint.y - bottomLeftPoint.y) < maxY,
).length
}
if (rightBottomCnt === 0) {
bottomRightPoint = { x: x + width / 2, y: y + h }
rightBottomCnt = centerPoints.filter(
(centerPoint) => Math.abs(centerPoint.x - bottomRightPoint.x) < maxX && Math.abs(centerPoint.y - bottomRightPoint.y) < maxY,
).length
}
})
break
case 'north':
width = widthArr.reduce((acc, num) => acc + num, 0) / widthArr.length + horizontal
height = heightArr.reduce((acc, num) => acc + num, 0) / heightArr.length + vertical
heightArr.forEach((h) => {
if (bottomCell) return
bottomCell = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y - h)) < maxY)
if (leftBottomCnt === 0) {
bottomLeftPoint = { x: x + width / 2, y: y - h }
leftBottomCnt = centerPoints.filter(
(centerPoint) => Math.abs(centerPoint.x - bottomLeftPoint.x) < maxX && Math.abs(centerPoint.y - bottomLeftPoint.y) < maxY,
).length
}
if (rightBottomCnt === 0) {
bottomRightPoint = { x: x - width / 2, y: y - h }
rightBottomCnt = centerPoints.filter(
(centerPoint) => Math.abs(centerPoint.x - bottomRightPoint.x) < maxX && Math.abs(centerPoint.y - bottomRightPoint.y) < maxY,
).length
}
})
break
case 'east':
widthArr.forEach((w) => {
if (bottomCell) return
bottomCell = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - (x + w)) < maxX && Math.abs(centerPoint.y - y) < maxY)
if (leftBottomCnt === 0) {
bottomLeftPoint = { x: x + w, y: y + height / 2 }
leftBottomCnt = centerPoints.filter(
(centerPoint) => Math.abs(centerPoint.x - bottomLeftPoint.x) < maxX && Math.abs(centerPoint.y - bottomLeftPoint.y) < maxY,
).length
}
if (rightBottomCnt === 0) {
bottomRightPoint = { x: x + w, y: y - height / 2 }
rightBottomCnt = centerPoints.filter(
(centerPoint) => Math.abs(centerPoint.x - bottomRightPoint.x) < maxX && Math.abs(centerPoint.y - bottomRightPoint.y) < maxY,
).length
}
})
break
case 'west':
widthArr.forEach((w) => {
if (bottomCell) return
bottomCell = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - (x - w)) < maxX && Math.abs(centerPoint.y - y) < maxY)
if (leftBottomCnt === 0) {
bottomLeftPoint = { x: x - w, y: y - height / 2 }
leftBottomCnt = centerPoints.filter(
(centerPoint) => Math.abs(centerPoint.x - bottomLeftPoint.x) < maxX && Math.abs(centerPoint.y - bottomLeftPoint.y) < maxY,
).length
}
if (rightBottomCnt === 0) {
bottomRightPoint = { x: x - w, y: y + height / 2 }
rightBottomCnt = centerPoints.filter(
(centerPoint) => Math.abs(centerPoint.x - bottomRightPoint.x) < maxX && Math.abs(centerPoint.y - bottomRightPoint.y) < maxY,
).length
}
})
break
}
if (bottomCell) {
return
}
// 바로 아래에 셀이 없는 경우 물떼세 배치가 왼쪽 되어있는 셀을 찾는다.
if (leftBottomCnt + rightBottomCnt === 1) {
exposedHalfBottom++
if (leftBottomCnt === 1) {
rightExposedHalfBottomPoints.push(centerPoint)
}
if (rightBottomCnt === 1) {
leftExposedHalfBottomPoints.push(centerPoint)
}
} else if (leftBottomCnt + rightBottomCnt === 0) {
exposedBottomPoints.push(centerPoint)
}
})
// 노출상면 및 접면 체크
centerPoints.forEach((centerPoint, index) => {
let { x, y, width, height, widthArr, heightArr } = { ...centerPoint }
let topCell
let topLeftPoint
let topRightPoint
let leftTopCnt = 0
let rightTopCnt = 0
switch (direction) {
case 'south':
width = width + horizontal
height = height + vertical
heightArr.forEach((h) => {
if (topCell) return
topCell = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y + h)) < maxY)
if (leftTopCnt === 0) {
topLeftPoint = { x: x - width / 2, y: y - h }
leftTopCnt = centerPoints.filter(
(centerPoint) => Math.abs(centerPoint.x - topLeftPoint.x) < maxX && Math.abs(centerPoint.y - topLeftPoint.y) < maxY,
).length
}
if (rightTopCnt === 0) {
topRightPoint = { x: x + width / 2, y: y - h }
rightTopCnt = centerPoints.filter(
(centerPoint) => Math.abs(centerPoint.x - topRightPoint.x) < maxX && Math.abs(centerPoint.y - topRightPoint.y) < maxY,
).length
}
})
break
case 'north':
height = height + vertical
heightArr.forEach((h) => {
if (topCell) return
topCell = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y - h)) < maxY)
if (leftTopCnt === 0) {
topLeftPoint = { x: x + width / 2, y: y + h }
leftTopCnt = centerPoints.filter(
(centerPoint) => Math.abs(centerPoint.x - topLeftPoint.x) < maxX && Math.abs(centerPoint.y - topLeftPoint.y) < maxY,
).length
}
if (rightTopCnt === 0) {
topRightPoint = { x: x - width / 2, y: y + h }
rightTopCnt = centerPoints.filter(
(centerPoint) => Math.abs(centerPoint.x - topRightPoint.x) < maxX && Math.abs(centerPoint.y - topRightPoint.y) < maxY,
).length
}
})
break
case 'east':
width = width + horizontal
widthArr.forEach((w) => {
if (topCell) return
topCell = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - (x + w)) < maxX && Math.abs(centerPoint.y - y) < maxY)
if (leftTopCnt === 0) {
topLeftPoint = { x: x - w, y: y + height / 2 }
leftTopCnt = centerPoints.filter(
(centerPoint) => Math.abs(centerPoint.x - topLeftPoint.x) < maxX && Math.abs(centerPoint.y - topLeftPoint.y) < maxY,
).length
}
if (rightTopCnt === 0) {
topRightPoint = { x: x - w, y: y - height / 2 }
rightTopCnt = centerPoints.filter(
(centerPoint) => Math.abs(centerPoint.x - topRightPoint.x) < maxX && Math.abs(centerPoint.y - topRightPoint.y) < maxY,
).length
}
})
break
case 'west':
width = width + horizontal
widthArr.forEach((w) => {
if (topCell) return
topCell = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - (x - w)) < maxX && Math.abs(centerPoint.y - y) < maxY)
if (leftTopCnt === 0) {
topLeftPoint = { x: x + w, y: y - height / 2 }
leftTopCnt = centerPoints.filter(
(centerPoint) => Math.abs(centerPoint.x - topLeftPoint.x) < maxX && Math.abs(centerPoint.y - topLeftPoint.y) < maxY,
).length
}
if (rightTopCnt === 0) {
topRightPoint = { x: x + w, y: y + height / 2 }
rightTopCnt = centerPoints.filter(
(centerPoint) => Math.abs(centerPoint.x - topRightPoint.x) < maxX && Math.abs(centerPoint.y - topRightPoint.y) < maxY,
).length
}
})
break
}
if (topCell) {
touchDimension++
return
}
if (leftTopCnt + rightTopCnt === 2) {
touchDimension++
return
}
if (leftTopCnt + rightTopCnt === 1) {
exposedHalfTop++
halfTouchDimension++
if (leftTopCnt === 1) {
rightExposedHalfTopPoints.push(centerPoint)
}
if (rightTopCnt === 1) {
leftExposedHalfTopPoints.push(centerPoint)
}
return
}
if (leftTopCnt + rightTopCnt === 0) {
exposedTop++
}
})
// 완전 노출 하면 계산
const groupPoints = groupCoordinates(centerPoints, modules[0], direction)
groupPoints.forEach((group) => {
let maxY = group.reduce((acc, cur) => (acc.y > cur.y ? acc : cur)).y
let minY = group.reduce((acc, cur) => (acc.y < cur.y ? acc : cur)).y
let maxX = group.reduce((acc, cur) => (acc.x > cur.x ? acc : cur)).x
let minX = group.reduce((acc, cur) => (acc.x < cur.x ? acc : cur)).x
let maxYCenterPoints = group.filter((centerPoint) => Math.abs(centerPoint.y - maxY) < 2)
let minYCenterPoints = group.filter((centerPoint) => Math.abs(centerPoint.y - minY) < 2)
let maxXCenterPoints = group.filter((centerPoint) => Math.abs(centerPoint.x - maxX) < 2)
let minXCenterPoints = group.filter((centerPoint) => Math.abs(centerPoint.x - minX) < 2)
switch (direction) {
case 'south':
exposedBottom += maxYCenterPoints.length
break
case 'north':
exposedBottom += minYCenterPoints.length
break
case 'east':
exposedBottom += maxXCenterPoints.length
break
case 'west':
exposedBottom += minXCenterPoints.length
break
}
})
return {
exposedBottom,
exposedHalfBottom,
exposedTop,
exposedHalfTop,
touchDimension,
halfTouchDimension,
exposedBottomPoints,
leftExposedHalfBottomPoints,
rightExposedHalfBottomPoints,
leftExposedHalfTopPoints,
rightExposedHalfTopPoints,
centerPoints,
}
}
// polygon 내부 cell들의 centerPoint 배열을 그룹화 해서 반환
const groupCoordinates = (points, moduleExample, direction) => {
const groups = []
const visited = new Set()
const width = Math.floor(moduleExample.width)
const height = Math.floor(moduleExample.height)
const horizonPadding = 0 // 가로 패딩
const verticalPadding = 0 // 세로 패딩
function isAdjacent(p1, p2) {
const dx = Math.abs(p1.x - p2.x)
const dy = Math.abs(p1.y - p2.y)
return (
(Math.abs(width + horizonPadding - dx) < 2 && dy < 2) ||
(dx < 2 && Math.abs(dy - height + verticalPadding)) < 2 ||
(Math.abs(dx - width / 2 + horizonPadding / 2) < 2 && Math.abs(dy - height + verticalPadding) < 2)
)
}
function dfs(point, group) {
visited.add(`${point.x},${point.y}`)
group.push(point)
for (const nextPoint of points) {
const key = `${nextPoint.x},${nextPoint.y}`
if (!visited.has(key) && isAdjacent(point, nextPoint)) {
dfs(nextPoint, group)
}
}
}
for (const point of points) {
const key = `${point.x},${point.y}`
if (!visited.has(key)) {
const group = []
dfs(point, group)
groups.push(group)
}
}
return groups
}
// 각도에 따른 길이 반환
function getTrestleLength(length, degree) {
if (roofSizeSet !== 1) {
// 복시도 입력이 아닌경우 그냥 길이 return
return length
}
const radians = (degree * Math.PI) / 180
return length * Math.cos(radians)
}
// 견적서 아이템 조회 api parameter 생성
const getTrestleParams = (surface, exposedBottomModules) => {
const result = calculateForApi(surface)
const eaveBar = canvas.getObjects().filter((obj) => obj.surfaceId === surface.id && obj.name === 'eaveBar')
const halfEaveBar = canvas.getObjects().filter((obj) => obj.surfaceId === surface.id && obj.name === 'halfEaveBar')
const rackList = canvas.getObjects().filter((obj) => obj.surfaceId === surface.id && obj.name === 'rack')
const smartRackList = canvas.getObjects().filter((obj) => obj.surfaceId === surface.id && obj.name === 'smartRack')
// smartRackList을 smartRackId 기준으로 그룹화 한 배열
const smartRackGroup = smartRackList.reduce((acc, cur) => {
if (!acc[cur.smartRackId]) {
acc[cur.smartRackId] = []
}
acc[cur.smartRackId].push(cur)
return acc
}, {})
const bracketList = canvas.getObjects().filter((obj) => obj.surfaceId === surface.id && obj.name === 'bracket')
let rackParams = rackList.map((rack, index) => {
return {
seq: index,
itemId: rack.rackId,
rackFittingCnt: rack.supFitQty,
rackRows: rack.rackRowsCd,
}
})
const parent = canvas.getObjects().find((obj) => obj.id === surface.parentId)
const roofMaterialIndex = parent.roofMaterial.index
const moduleSelection = moduleSelectionData?.roofConstructions?.find((construction) => construction.roofIndex === roofMaterialIndex)
const { common, module } = moduleSelectionData
// const { constTp } = construction
let { cvrPlvrYn, rackYn } = surface.trestleDetail
const { trestleMkrCd, constMthdCd, roofBaseCd } = moduleSelection.trestle
const { illuminationTp, instHt, stdSnowLd, stdWindSpeed } = common
const { constTp } = moduleSelection.construction
const { addRoof } = moduleSelection
return {
moduleTpCd: module.itemTp,
roofMatlCd: parent.roofMaterial.roofMatlCd,
mixMatlNo: module.mixMatlNo,
raftBaseCd: addRoof.raft ?? addRoof.raftBaseCd,
inclCd: addRoof.pitch,
roofPitch: !addRoof.roofPchBase ? addRoof.roofPchBase : Number(addRoof.roofPchBase),
exposedLowerBottomTotCnt: result.exposedBottom, // 노출 최하면 갯수
exposedHalfBottomTotCnt: result.exposedHalfBottom, // 노출 반하면 갯수
exposedTopTotCnt: result.exposedTop, // 노출 상면 총 수
exposedHalfTopTotCnt: result.exposedHalfTop, // 노출 반상면 총 수
exposedBottomTotCnt: result.exposedBottomPoints.length, // 노출 하면 수
touchedSurfaceTotCnt: result.touchDimension, // 접면 총 수
touchedHalfSurfaceTotCnt: result.halfTouchDimension, // 반접면 총 수
moduleTotCnt: surface.modules.length, // 모듈 총 수
moduleRowsTotCnt: surface.moduleRowsTotCnt, // 모듈 총 단 수
eavesTotCnt: eaveBar.length,
eavesHalfTotCnt: halfEaveBar.length,
rackYn,
racks: rackParams,
rackTotCnt: rackList.length ?? 0 + smartRackGroup.length ?? 0,
rackFittingTotCnt: bracketList.length,
moduleRows: getMostLeftModules(surface, exposedBottomModules),
cvrYn: moduleSelection.construction.setupCover ? 'Y' : 'N',
snowGdYn: moduleSelection.construction.setupSnowCover ? 'Y' : 'N',
plvrYn: cvrPlvrYn,
// modules: getModules(surface), // 2025-02-06 api 수정
trestleMkrCd,
constMthdCd,
roofBaseCd,
illuminationTp,
instHt,
stdSnowLd,
stdWindSpeed,
constTp,
}
}
// 전체 모듈 파라미터 생성
const getModulesParam = (allModules) => {
const params = allModules.map((module, index) => {
return {
moduleTpCd: module.moduleInfo.itemTp,
moduleItemId: module.moduleInfo.itemId,
}
})
//params를 moduleTpCd, moduleItemId로 그룹화 하면서 cnt를 계산
const groupedParams = params.reduce((acc, cur) => {
const key = `${cur.moduleTpCd}-${cur.moduleItemId}`
if (!acc[key]) {
acc[key] = {
moduleTpCd: cur.moduleTpCd,
moduleItemId: cur.moduleItemId,
cnt: 0,
}
}
acc[key].cnt++
return acc
}, {})
// map 형태의 데이터를 배열로 변환
return Object.values(groupedParams).map((groupedParam, index) => {
return {
moduleTpCd: groupedParam.moduleTpCd,
moduleItemId: groupedParam.moduleItemId,
moduleCnt: groupedParam.cnt,
}
})
}
// 키값의 차이가 2이하인 경우 한개로 합침
function mergeCloseKeys(data) {
// 키 값을 숫자로 변환 후 정렬
const keys = Object.keys(data)
.map(parseFloat)
.sort((a, b) => a - b)
const result = {}
let baseKey = keys[0]
result[baseKey.toString()] = [...data[baseKey.toString()]]
for (let i = 1; i < keys.length; i++) {
const currentKey = keys[i]
const prevKey = baseKey
if (Math.abs(currentKey - prevKey) <= 2) {
// 키 차이가 2 이하인 경우 병합
result[baseKey.toString()].push(...data[currentKey.toString()])
} else {
// 새로운 그룹 시작
baseKey = currentKey
result[baseKey.toString()] = [...data[currentKey.toString()]]
}
}
return result
}
// 가장 왼쪽에 있는 모듈을 기준으로 같은 단에 있는 모듈들 파라미터 생성
const getMostLeftModules = (surface, exposedBottomModules) => {
const { direction, modules, isChidory } = surface
const parent = canvas.getObjects().find((obj) => obj.id === surface.parentId)
const roofMaterialIndex = parent.roofMaterial.index
const construction = moduleSelectionData?.roofConstructions?.find((construction) => construction.roofIndex === roofMaterialIndex).construction
let isEaveBar = construction.setupCover
let isSnowGuard = construction.setupSnowCover
let { rackYn, cvrPlvrYn, moduleIntvlHor, moduleIntvlVer, rackQty, lessSupFitQty } = surface.trestleDetail
if (rackYn === 'N') {
rackQty = lessSupFitQty
}
// 같은 단에 있는 모듈들의 리스트
let sameLineModuleList = []
let result = []
if (direction === 'south') {
// 모듈의 top으로 groupBy
let groupedByTop = modules.reduce((acc, module) => {
const key = module.top
if (!acc[key]) {
acc[key] = []
}
acc[key].push(module)
return acc
}, {})
groupedByTop = mergeCloseKeys(groupedByTop)
// groupedByTop의 키값을 기준으로 정렬한 데이터를 배열로 변환
sameLineModuleList = Object.values(groupedByTop).sort((a, b) => b[0].top - a[0].top)
} else if (direction === 'north') {
let groupedByTop = modules.reduce((acc, module) => {
const key = module.top
if (!acc[key]) {
acc[key] = []
}
acc[key].push(module)
return acc
}, {})
groupedByTop = mergeCloseKeys(groupedByTop)
sameLineModuleList = Object.values(groupedByTop).sort((a, b) => a[0].top - b[0].top)
} else if (direction === 'east') {
let groupedByLeft = modules.reduce((acc, module) => {
const key = module.left
if (!acc[key]) {
acc[key] = []
}
acc[key].push(module)
return acc
}, {})
groupedByLeft = mergeCloseKeys(groupedByLeft)
sameLineModuleList = Object.values(groupedByLeft).sort((a, b) => b[0].left - a[0].left)
} else if (direction === 'west') {
let groupedByLeft = modules.reduce((acc, module) => {
const key = module.left
if (!acc[key]) {
acc[key] = []
}
acc[key].push(module)
return acc
}, {})
//groupedByLeft의 키값의 차이가 2이하인 경우 같은 라인으로 합친다.
groupedByLeft = mergeCloseKeys(groupedByLeft)
sameLineModuleList = Object.values(groupedByLeft).sort((a, b) => a[0].left - b[0].left)
}
sameLineModuleList.forEach((modules, index) => {
const moduleRowResultData = {
seq: index,
moduleItemId: modules[0].moduleInfo.itemId,
moduleTpCd: modules[0].moduleInfo.itemTp,
moduleCnt: modules.length,
exposedBottomCnt: 0,
exposedHalfBottomCnt: 0,
exposedTopCnt: 0,
exposedHalfTopCnt: 0,
touchedSurfaceCnt: 0,
touchedHalfSurfaceCnt: 0,
exposedBottomBracketCnt: 0,
exposedHalfBottomBracketCnt: 0,
exposedTopBracketCnt: 0,
exposedHalfTopBracketCnt: 0,
touchedSurfaceBracketCnt: 0,
touchedHalfSurfaceBracketCnt: 0,
eavesCnt: 0,
eavesHalfCnt: 0,
exposedSideEavesCnt: 0,
}
if (direction === 'south') {
modules.sort((a, b) => a.left - b.left)
} else if (direction === 'north') {
modules.sort((a, b) => b.left - a.left)
} else if (direction === 'east') {
modules.sort((a, b) => a.top - b.top)
} else if (direction === 'west') {
modules.sort((a, b) => b.top - a.top)
}
// 모듈 하면,최하면 등 구해야함
modules.forEach((module, index) => {
// 해당 모듈 주변에 다른 모듈이 있는지 확인
let {
bottomModule,
topModule,
halfBottomLeftModule,
halfBottomRightModule,
halfTopLeftModule,
halfTopRightModule,
leftModule,
rightModule,
bottomLeftModule,
bottomRightModule,
} = findSideModule(module, surface)
if (bottomModule) {
moduleRowResultData.touchedSurfaceCnt++
if (rackYn === 'N') {
moduleRowResultData.touchedSurfaceBracketCnt += rackQty
}
}
if (!bottomModule) {
if (halfBottomLeftModule && halfBottomRightModule) {
moduleRowResultData.touchedSurfaceCnt++
if (rackYn === 'N') {
moduleRowResultData.touchedSurfaceBracketCnt += rackQty
}
} else if ((halfBottomLeftModule && !halfBottomRightModule) || (!halfBottomLeftModule && halfBottomRightModule)) {
moduleRowResultData.touchedHalfSurfaceCnt++
moduleRowResultData.exposedHalfBottomCnt++
if (rackYn === 'N') {
if (rackQty !== 3) {
// 3개가 아닌경우는 반반
moduleRowResultData.exposedHalfBottomBracketCnt += rackQty / 2
moduleRowResultData.touchedHalfSurfaceBracketCnt += rackQty / 2
} else {
// 3개인 경우 왼쪽 아래가 없는 경우 touched는 2개, exposed는 1개
if (!halfBottomLeftModule && findSamePointInBottom(exposedBottomModules, module, direction)) {
moduleRowResultData.exposedHalfBottomBracketCnt += 2
moduleRowResultData.touchedHalfSurfaceBracketCnt += 1
} else if (!halfBottomLeftModule && !findSamePointInBottom(exposedBottomModules, module, direction)) {
// 왼쪽 아래가 없고, 하단에 같은 점이 없는 경우는 touched는 1개, exposed는 2개
moduleRowResultData.exposedHalfBottomBracketCnt += 1
moduleRowResultData.touchedHalfSurfaceBracketCnt += 2
} else if (!halfBottomRightModule && findSamePointInBottom(exposedBottomModules, module, direction)) {
// 오른쪽 아래가 없고, 하단에 같은 점이 있는 경우는 exposed는 2개, touched는 1개
moduleRowResultData.exposedHalfBottomBracketCnt += 1
moduleRowResultData.touchedHalfSurfaceBracketCnt += 2
} else if (!halfBottomRightModule && !findSamePointInBottom(exposedBottomModules, module, direction)) {
// 오른쪽 아래가 없고, 하단에 같은 점이 없는 경우는 exposed는 1개, touched는 2개
moduleRowResultData.exposedHalfBottomBracketCnt += 2
moduleRowResultData.touchedHalfSurfaceBracketCnt += 1
}
}
}
if (cvrPlvrYn === 'Y') {
moduleRowResultData.eavesHalfCnt++
if (bottomLeftModule || bottomRightModule || halfBottomLeftModule || halfBottomRightModule) {
//처마커버 한개 노출 추가
moduleRowResultData.exposedSideEavesCnt++
}
}
} else {
moduleRowResultData.exposedBottomCnt++
if (rackYn === 'N') {
moduleRowResultData.exposedBottomBracketCnt += rackQty
}
if (isEaveBar) {
moduleRowResultData.eavesCnt++
if ((rightModule && !leftModule) || (!rightModule && leftModule)) {
// 둘중 하나가 없는경우는 처마커버 노출 추가
moduleRowResultData.exposedSideEavesCnt++
} else if (!rightModule && !leftModule) {
// 양쪽 둘다 없는경우는 처마커버 노출 2개 추가
moduleRowResultData.exposedSideEavesCnt += 2
}
}
}
}
if (!topModule) {
if ((halfTopLeftModule && !halfTopRightModule) || (!halfTopLeftModule && halfTopRightModule)) {
moduleRowResultData.exposedHalfTopCnt++
if (rackYn === 'N') {
if (rackQty !== 3) {
moduleRowResultData.exposedHalfTopBracketCnt += rackQty / 2
}
}
} else if (!halfTopLeftModule && !halfTopRightModule) {
moduleRowResultData.exposedTopCnt++
if (rackYn === 'N') {
moduleRowResultData.exposedTopBracketCnt += rackQty
}
}
}
})
result.push(moduleRowResultData)
})
canvas.renderAll()
return result
}
// 해당 모듈이 해당 설치면에서 상하좌우, 대각선에 있는지 확인
const findSideModule = (module, surface) => {
const { direction, modules } = surface
let { rackYn, cvrPlvrYn, moduleIntvlHor, moduleIntvlVer, rackQty, lessSupFitQty } = surface.trestleDetail
const centerPoints = getCenterPoints(surface)
const horizontal = ['south', 'north'].includes(direction) ? moduleIntvlHor : moduleIntvlVer
const vertical = ['south', 'north'].includes(direction) ? moduleIntvlVer : moduleIntvlHor
const maxX = MODULE_MARGIN
const maxY = MODULE_MARGIN
let { widthArr, heightArr } = centerPoints[0]
let width = widthArr.reduce((acc, num) => acc + num, 0) / widthArr.length
let height = heightArr.reduce((acc, num) => acc + num, 0) / heightArr.length
let { x, y } = { ...module.getCenterPoint() }
let halfBottomLeftPoint
let halfBottomRightPoint
let halfTopLeftPoint
let halfTopRightPoint
let leftPoint
let rightPoint
let bottomLeftPoint
let bottomRightPoint
let bottomModule
let topModule
let halfBottomLeftModule
let halfBottomRightModule
let halfTopLeftModule
let halfTopRightModule
let leftModule
let rightModule
let bottomLeftModule
let bottomRightModule
switch (direction) {
case 'south':
width = width + horizontal
height = height + vertical
heightArr.forEach((h) => {
if (!bottomModule) {
bottomModule = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y + h)) < maxY)
}
if (!topModule) {
topModule = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y - h)) < maxY)
}
if (!halfBottomLeftModule) {
halfBottomLeftPoint = { x: x - width / 2, y: y + h }
halfBottomLeftModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - halfBottomLeftPoint.x) < maxX && Math.abs(centerPoint.y - halfBottomLeftPoint.y) < maxY,
)
}
if (!halfBottomRightModule) {
halfBottomRightPoint = { x: x + width / 2, y: y + h }
halfBottomRightModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - halfBottomRightPoint.x) < maxX && Math.abs(centerPoint.y - halfBottomRightPoint.y) < maxY,
)
}
if (!halfTopLeftModule) {
halfTopLeftPoint = { x: x - width / 2, y: y - h }
halfTopLeftModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - halfTopLeftPoint.x) < maxX && Math.abs(centerPoint.y - halfTopLeftPoint.y) < maxY,
)
}
if (!halfTopRightModule) {
halfTopRightPoint = { x: x + width / 2, y: y - h }
halfTopRightModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - halfTopRightPoint.x) < maxX && Math.abs(centerPoint.y - halfTopRightPoint.y) < maxY,
)
}
if (!leftModule) {
leftPoint = { x: x - width, y: y }
leftModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - leftPoint.x) < maxX && Math.abs(centerPoint.y - leftPoint.y) < maxY,
)
}
if (!rightModule) {
rightPoint = { x: x + width, y: y }
rightModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - rightPoint.x) < maxX && Math.abs(centerPoint.y - rightPoint.y) < maxY,
)
}
if (!bottomLeftModule) {
bottomLeftPoint = { x: x - width, y: y + h }
bottomLeftModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - bottomLeftPoint.x) < maxX && Math.abs(centerPoint.y - bottomLeftPoint.y) < maxY,
)
}
if (!bottomRightModule) {
bottomRightPoint = { x: x + width, y: y + h }
bottomRightModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - bottomRightPoint.x) < maxX && Math.abs(centerPoint.y - bottomRightPoint.y) < maxY,
)
}
})
break
case 'north':
width = width + horizontal
height = height + vertical
heightArr.forEach((h) => {
if (!bottomModule) {
bottomModule = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y - h)) < maxY)
}
if (!topModule) {
topModule = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y + h)) < maxY)
}
if (!halfBottomLeftModule) {
halfBottomLeftPoint = { x: x + width / 2, y: y - h }
halfBottomLeftModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - halfBottomLeftPoint.x) < maxX && Math.abs(centerPoint.y - halfBottomLeftPoint.y) < maxY,
)
}
if (!halfBottomRightModule) {
halfBottomRightPoint = { x: x - width / 2, y: y - h }
halfBottomRightModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - halfBottomRightPoint.x) < maxX && Math.abs(centerPoint.y - halfBottomRightPoint.y) < maxY,
)
}
if (!halfTopLeftModule) {
halfTopLeftPoint = { x: x + width / 2, y: y + h }
halfTopLeftModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - halfTopLeftPoint.x) < maxX && Math.abs(centerPoint.y - halfTopLeftPoint.y) < maxY,
)
}
if (!halfTopRightModule) {
halfTopRightPoint = { x: x - width / 2, y: y + h }
halfTopRightModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - halfTopRightPoint.x) < maxX && Math.abs(centerPoint.y - halfTopRightPoint.y) < maxY,
)
}
if (!leftModule) {
leftPoint = { x: x + width, y: y }
leftModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - leftPoint.x) < maxX && Math.abs(centerPoint.y - leftPoint.y) < maxY,
)
}
if (!rightModule) {
rightPoint = { x: x - width, y: y }
rightModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - rightPoint.x) < maxX && Math.abs(centerPoint.y - rightPoint.y) < maxY,
)
}
if (!bottomLeftModule) {
bottomLeftPoint = { x: x + width, y: y - h }
bottomLeftModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - bottomLeftPoint.x) < maxX && Math.abs(centerPoint.y - bottomLeftPoint.y) < maxY,
)
}
if (!bottomRightModule) {
bottomRightPoint = { x: x - width, y: y - h }
bottomRightModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - bottomRightPoint.x) < maxX && Math.abs(centerPoint.y - bottomRightPoint.y) < maxY,
)
}
})
break
case 'east':
widthArr.forEach((w) => {
if (!bottomModule) {
bottomModule = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - (x + w)) < maxX && Math.abs(centerPoint.y - y) < maxY)
}
if (!topModule) {
topModule = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - (x - w)) < maxX && Math.abs(centerPoint.y - y) < maxY)
}
if (!halfBottomLeftModule) {
halfBottomLeftPoint = { x: x + w, y: y - height / 2 }
halfBottomLeftModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - halfBottomLeftPoint.x) < maxX && Math.abs(centerPoint.y - halfBottomLeftPoint.y) < maxY,
)
}
if (!halfBottomRightModule) {
halfBottomRightPoint = { x: x + w, y: y - height / 2 }
halfBottomRightModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - halfBottomRightPoint.x) < maxX && Math.abs(centerPoint.y - halfBottomRightPoint.y) < maxY,
)
}
if (!halfTopLeftModule) {
halfTopLeftPoint = { x: x - w, y: y + height / 2 }
halfTopLeftModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - halfTopLeftPoint.x) < maxX && Math.abs(centerPoint.y - halfTopLeftPoint.y) < maxY,
)
}
if (!halfTopRightModule) {
halfTopRightPoint = { x: x - w, y: y - height / 2 }
halfTopRightModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - halfTopRightPoint.x) < maxX && Math.abs(centerPoint.y - halfTopRightPoint.y) < maxY,
)
}
if (!leftModule) {
leftPoint = { x: x, y: y + height }
leftModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - leftPoint.x) < maxX && Math.abs(centerPoint.y - leftPoint.y) < maxY,
)
}
if (!rightModule) {
rightPoint = { x: x, y: y - height }
rightModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - rightPoint.x) < maxX && Math.abs(centerPoint.y - rightPoint.y) < maxY,
)
}
if (!bottomLeftModule) {
bottomLeftPoint = { x: x + w, y: y + height }
bottomLeftModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - bottomLeftPoint.x) < maxX && Math.abs(centerPoint.y - bottomLeftPoint.y) < maxY,
)
}
if (!bottomRightModule) {
bottomRightPoint = { x: x + w, y: y - height }
bottomRightModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - bottomRightPoint.x) < maxX && Math.abs(centerPoint.y - bottomRightPoint.y) < maxY,
)
}
})
break
case 'west':
widthArr.forEach((w) => {
if (!bottomModule) {
bottomModule = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - (x - w)) < maxX && Math.abs(centerPoint.y - y) < maxY)
}
if (!topModule) {
topModule = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - (x + w)) < maxX && Math.abs(centerPoint.y - y) < maxY)
}
if (!halfBottomLeftModule) {
halfBottomLeftPoint = { x: x - w, y: y - height / 2 }
halfBottomLeftModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - halfBottomLeftPoint.x) < maxX && Math.abs(centerPoint.y - halfBottomLeftPoint.y) < maxY,
)
}
if (!halfBottomRightModule) {
halfBottomRightPoint = { x: x - w, y: y + height / 2 }
halfBottomRightModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - halfBottomRightPoint.x) < maxX && Math.abs(centerPoint.y - halfBottomRightPoint.y) < maxY,
)
}
if (!halfTopLeftModule) {
halfTopLeftPoint = { x: x + w, y: y - height / 2 }
halfTopLeftModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - halfTopLeftPoint.x) < maxX && Math.abs(centerPoint.y - halfTopLeftPoint.y) < maxY,
)
}
if (!halfTopRightModule) {
halfTopRightPoint = { x: x + w, y: y + height / 2 }
halfTopRightModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - halfTopRightPoint.x) < maxX && Math.abs(centerPoint.y - halfTopRightPoint.y) < maxY,
)
}
if (!leftModule) {
leftPoint = { x: x, y: y - height }
leftModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - leftPoint.x) < maxX && Math.abs(centerPoint.y - leftPoint.y) < maxY,
)
}
if (!rightModule) {
rightPoint = { x: x, y: y + height }
rightModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - rightPoint.x) < maxX && Math.abs(centerPoint.y - rightPoint.y) < maxY,
)
}
if (!bottomLeftModule) {
bottomLeftPoint = { x: x - w, y: y - height }
bottomLeftModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - bottomLeftPoint.x) < maxX && Math.abs(centerPoint.y - bottomLeftPoint.y) < maxY,
)
}
if (!bottomRightModule) {
bottomRightPoint = { x: x - w, y: y + height }
bottomRightModule = centerPoints.find(
(centerPoint) => Math.abs(centerPoint.x - bottomRightPoint.x) < maxX && Math.abs(centerPoint.y - bottomRightPoint.y) < maxY,
)
}
})
break
}
return {
bottomModule,
topModule,
halfBottomLeftModule,
halfBottomRightModule,
halfTopLeftModule,
halfTopRightModule,
leftModule,
rightModule,
bottomLeftModule,
bottomRightModule,
}
}
const clear = () => {
canvas
.getObjects()
.filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
.forEach((obj) => {
obj.isComplete = false
})
canvas.getObjects().forEach((obj) => {
if (obj.name === 'eaveBar' || obj.name === 'rack' || obj.name === 'halfEaveBar' || obj.name === 'smartRack' || obj.name === 'bracket') {
canvas.remove(obj)
}
})
resetCircuits()
}
// 전모듈 의 회로번호 visible false 처리
// 가대 설치 전 필요
const setViewCircuitNumberTexts = (visible) => {
const circuitNumberTexts = canvas.getObjects().filter((obj) => obj.name === 'circuitNumber')
circuitNumberTexts.forEach((text) => {
text.visible = visible
})
canvas.renderAll()
}
// 가대 설치 완료 전,후 모든 surface의 isComplete를 변경
const setAllModuleSurfaceIsComplete = (bool) => {
const surfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
surfaces.forEach((surface) => {
surface.isComplete = bool
})
}
return { apply, getTrestleParams, clear, setViewCircuitNumberTexts, getEstimateData, setAllModuleSurfaceIsComplete }
}