2683 lines
102 KiB
JavaScript
2683 lines
102 KiB
JavaScript
import { useRecoilValue } from 'recoil'
|
|
import { canvasState, currentAngleTypeSelector } from '@/store/canvasAtom'
|
|
import { POLYGON_TYPE } 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'
|
|
|
|
// 회로 및 가대설정
|
|
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 apply = () => {
|
|
const notAllocationModules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE && !obj.circuit)
|
|
if (notAllocationModules.length > 0) {
|
|
swalFire({ text: '回路番号が設定されていないモジュールがあります。 番号を設定しなおすか、 パネルを削除してください。', icon: 'error' })
|
|
return null
|
|
}
|
|
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
|
|
const construction = moduleSelectionData?.roofConstructions?.find((construction) => construction.roofIndex === roofMaterialIndex).construction
|
|
if (!construction) {
|
|
alert('앞에서 셋팅 안됨')
|
|
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] }
|
|
})
|
|
}
|
|
|
|
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) {
|
|
alert('치조불가공법입니다.')
|
|
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: 'eaveBar',
|
|
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: 'halfEaveBar',
|
|
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: 'halfEaveBar',
|
|
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, isComplete: true })
|
|
})
|
|
|
|
return setEstimateData()
|
|
} catch (e) {
|
|
// 에러 발생시 가대 초기화
|
|
console.error(e)
|
|
// clear()
|
|
setViewCircuitNumberTexts(true)
|
|
return null
|
|
}
|
|
}
|
|
|
|
//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 setEstimateData = 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: itemList, data2, result } = await getQuotationItem(params)
|
|
|
|
if (result.resultCode === 'E') {
|
|
swalFire({ text: result.resultMsg, icon: 'error' })
|
|
return null
|
|
}
|
|
|
|
//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, pitch: slope, moduleCompass, surfaceCompass } = parent
|
|
const roofMaterialIndex = parent.roofMaterial.index
|
|
const { nameJp: roofMaterialIdMulti } = roofMaterial
|
|
const moduleSelection = moduleSelectionData?.roofConstructions?.find((construction) => construction.roofIndex === roofMaterialIndex)
|
|
const { constTp: constructSpecification, constTpJp: constructSpecificationMulti } = moduleSelection.construction
|
|
const {
|
|
trestleMkrCd,
|
|
constMthdCd: supportMethodId,
|
|
roofBaseCd,
|
|
trestleMkrCdJp: supportMeaker,
|
|
constMthdCdJp: supportMethodIdMulti,
|
|
} = moduleSelection.trestle
|
|
|
|
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: roofMaterial.roofMatlCd,
|
|
supportMethodId,
|
|
constructSpecification,
|
|
constructSpecificationMulti,
|
|
roofMaterialIdMulti,
|
|
supportMethodIdMulti,
|
|
supportMeaker,
|
|
slope,
|
|
classType: currentAngleType === 'slope' ? '0' : '1',
|
|
angle: getDegreeByChon(slope),
|
|
azimuth: surfaceCompass ?? moduleCompass ?? 0,
|
|
moduleList,
|
|
}
|
|
})
|
|
|
|
// circuitItemList 중복제거
|
|
circuitItemList = circuitItemList.filter((item, index) => circuitItemList.indexOf(item) === index)
|
|
circuitItemList = circuitItemList.map((circuitId) => {
|
|
return {
|
|
itemId: circuitId,
|
|
}
|
|
})
|
|
|
|
return { itemList, northArrangement, roofSurfaceList, circuitItemList }
|
|
}
|
|
|
|
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 = 2 + horizontal * 3
|
|
let maxY = 2 + vertical * 3
|
|
|
|
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 = 2 + horizontal * 3
|
|
let maxY = 2 + vertical * 3
|
|
|
|
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))
|
|
})
|
|
|
|
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))
|
|
})
|
|
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 = 2 + horizontal * 3
|
|
let maxY = 2 + vertical * 3
|
|
|
|
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))
|
|
})
|
|
|
|
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))
|
|
})
|
|
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
|
|
}
|
|
|
|
const drawRacks = (rackInfos, rackQty, rackIntvlPct, module, direction, l, rackYn) => {
|
|
if (!rackInfos) {
|
|
return
|
|
}
|
|
const { width, height, left, top, lastX, lastY, surfaceId } = module
|
|
const surface = canvas.getObjects().find((obj) => obj.id === surfaceId)
|
|
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: 'smartRack',
|
|
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: '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: 'smartRack',
|
|
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: '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: 'smartRack',
|
|
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: '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: 'smartRack',
|
|
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: '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
|
|
}
|
|
}
|
|
}
|
|
|
|
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: '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: '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: '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: '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: '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 = 2 + (horizontal / 10) * 3
|
|
const maxY = 2 + (vertical / 10) * 3
|
|
|
|
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,
|
|
inclCd: addRoof.pitch,
|
|
roofPitch: 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++
|
|
}
|
|
}
|
|
}
|
|
}
|
|
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 = 2 + horizontal * 3
|
|
const maxY = 2 + vertical * 3
|
|
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)
|
|
}
|
|
})
|
|
}
|
|
|
|
// 전모듈 의 회로번호 visible false 처리
|
|
// 가대 설치 전 필요
|
|
const setViewCircuitNumberTexts = (visible) => {
|
|
const circuitNumberTexts = canvas.getObjects().filter((obj) => obj.name === 'circuitNumber')
|
|
circuitNumberTexts.forEach((text) => {
|
|
text.visible = visible
|
|
})
|
|
canvas.renderAll()
|
|
}
|
|
|
|
return { apply, getTrestleParams, clear, setViewCircuitNumberTexts }
|
|
}
|