회로 할당 작업중
This commit is contained in:
parent
982738939a
commit
e885e7b939
@ -164,6 +164,11 @@ export const SAVE_KEY = [
|
||||
'moduleCompass',
|
||||
'isFixed',
|
||||
'modules',
|
||||
'rackLen',
|
||||
'itemId',
|
||||
'supFitQty',
|
||||
'supFitIntvlPct',
|
||||
'rackLen',
|
||||
]
|
||||
|
||||
export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype]
|
||||
|
||||
@ -12,12 +12,16 @@ import { get } from 'react-hook-form'
|
||||
import { correntObjectNoState } from '@/store/settingAtom'
|
||||
import { useRecoilValue } from 'recoil'
|
||||
import { GlobalDataContext } from '@/app/GlobalDataProvider'
|
||||
|
||||
import { useRecoilState } from 'recoil'
|
||||
import { powerConditionalState } from '@/store/circuitTrestleAtom'
|
||||
import { POLYGON_TYPE } from '@/common/common'
|
||||
import { useSwal } from '@/hooks/useSwal'
|
||||
import { canvasState } from '@/store/canvasAtom'
|
||||
|
||||
import { trestleDetailData } from '@/common/example'
|
||||
import { useTrestle } from '@/hooks/module/useTrestle'
|
||||
|
||||
const ALLOCATION_TYPE = {
|
||||
AUTO: 'auto',
|
||||
PASSIVITY: 'passivity',
|
||||
@ -29,12 +33,17 @@ export default function CircuitTrestleSetting({ id }) {
|
||||
// 탭 번호 2: 회로 할당
|
||||
const [tabNum, setTabNum] = useState(1)
|
||||
const [allocationType, setAllocationType] = useState(ALLOCATION_TYPE.AUTO)
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
const { swalFire } = useSwal()
|
||||
|
||||
const apply = () => {
|
||||
closePopup(id)
|
||||
}
|
||||
const [makers, setMakers] = useState([])
|
||||
const [series, setSeries] = useState([])
|
||||
const [models, setModels] = useState([])
|
||||
const [selectedMaker, setSelectedMaker] = useState(null)
|
||||
const [selectedModels, setSelectedModels] = useState(null)
|
||||
const [selectedSeries, setSelectedSeries] = useState(null)
|
||||
const correntObjectNo = useRecoilValue(correntObjectNoState)
|
||||
const { getPcsMakerList } = useMasterController()
|
||||
const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext)
|
||||
const { apply } = useTrestle()
|
||||
|
||||
useEffect(() => {
|
||||
// console.log(canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE))
|
||||
|
||||
@ -1136,247 +1136,6 @@ export function useModuleBasicSetting() {
|
||||
// calculateForApi()
|
||||
}
|
||||
|
||||
const calculateForApi = () => {
|
||||
const moduleSufaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
|
||||
|
||||
const results = []
|
||||
|
||||
moduleSufaces.forEach((moduleSurface) => {
|
||||
const centerPoints = []
|
||||
const direction = moduleSurface.direction
|
||||
const modules = moduleSurface.modules
|
||||
|
||||
modules.forEach((module, index) => {
|
||||
module.tempIndex = index
|
||||
const { x, y } = module.getCenterPoint()
|
||||
const { width, height } = module
|
||||
centerPoints.push({ x, y, width: Math.floor(width), height: Math.floor(height), index })
|
||||
})
|
||||
|
||||
if (centerPoints.length === 0) return
|
||||
|
||||
//완전 노출 하면
|
||||
let exposedBottom = 0
|
||||
// 반 노출 하면
|
||||
let exposedHalfBottom = 0
|
||||
// 완전 노출 상면
|
||||
let exposedTop = 0
|
||||
//반 노출 상면
|
||||
let exposedHalfTop = 0
|
||||
// 완전 접면
|
||||
let touchDimension = 0
|
||||
//반접면
|
||||
let halfTouchDimension = 0
|
||||
// 노출하면 체크
|
||||
centerPoints.forEach((centerPoint, index) => {
|
||||
const { x, y, width, height } = centerPoint
|
||||
// centerPoints중에 현재 centerPoint와 x값이 같고, y값이 y-height값과 같은 centerPoint가 있는지 확인
|
||||
let bottomCell
|
||||
let bottomLeftPoint
|
||||
let bottomRightPoint
|
||||
let leftBottomCnt
|
||||
let rightBottomCnt
|
||||
|
||||
switch (direction) {
|
||||
case 'south':
|
||||
bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y + height)) < 2)
|
||||
bottomLeftPoint = { x: x - width / 2, y: y + height }
|
||||
bottomRightPoint = { x: x + width / 2, y: y + height }
|
||||
break
|
||||
case 'north':
|
||||
bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y - height)) < 2)
|
||||
bottomLeftPoint = { x: x + width / 2, y: y - height }
|
||||
bottomRightPoint = { x: x - width / 2, y: y - height }
|
||||
break
|
||||
case 'east':
|
||||
bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x - width)) < 2 && Math.abs(centerPoint.y - y) < 2)
|
||||
bottomLeftPoint = { x: x + width, y: y + height / 2 }
|
||||
bottomRightPoint = { x: x + width, y: y - height / 2 }
|
||||
break
|
||||
case 'west':
|
||||
bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x + width)) < 2 && Math.abs(centerPoint.y - y) < 2)
|
||||
bottomLeftPoint = { x: x - width, y: y - height / 2 }
|
||||
bottomRightPoint = { x: x - width, y: y + height / 2 }
|
||||
break
|
||||
}
|
||||
|
||||
if (bottomCell.length === 1) {
|
||||
return
|
||||
}
|
||||
|
||||
// 바로 아래에 셀이 없는 경우 물떼세 배치가 왼쪽 되어있는 셀을 찾는다.
|
||||
leftBottomCnt = centerPoints.filter(
|
||||
(centerPoint) => Math.abs(centerPoint.x - bottomLeftPoint.x) < 2 && Math.abs(centerPoint.y - bottomLeftPoint.y) < 2,
|
||||
).length
|
||||
rightBottomCnt = centerPoints.filter(
|
||||
(centerPoint) => Math.abs(centerPoint.x - bottomRightPoint.x) < 2 && Math.abs(centerPoint.y - bottomRightPoint.y) < 2,
|
||||
).length
|
||||
|
||||
if (leftBottomCnt + rightBottomCnt === 1) {
|
||||
exposedHalfBottom++
|
||||
return
|
||||
}
|
||||
})
|
||||
// 노출상면 체크
|
||||
|
||||
centerPoints.forEach((centerPoint, index) => {
|
||||
const { x, y, width, height } = centerPoint
|
||||
|
||||
let topCell
|
||||
let topLeftPoint
|
||||
let topRightPoint
|
||||
let leftTopCnt
|
||||
let rightTopCnt
|
||||
|
||||
switch (direction) {
|
||||
case 'south':
|
||||
topCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y - height)) < 2)
|
||||
topLeftPoint = { x: x - width / 2, y: y - height }
|
||||
topRightPoint = { x: x + width / 2, y: y - height }
|
||||
break
|
||||
case 'north':
|
||||
topCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y + height)) < 2)
|
||||
topLeftPoint = { x: x + width / 2, y: y + height }
|
||||
topRightPoint = { x: x - width / 2, y: y + height }
|
||||
break
|
||||
case 'east':
|
||||
topCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x - width)) < 2 && Math.abs(centerPoint.y - y) < 2)
|
||||
topLeftPoint = { x: x - width, y: y + height / 2 }
|
||||
topRightPoint = { x: x - width, y: y - height / 2 }
|
||||
break
|
||||
case 'west':
|
||||
topCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x + width)) < 2 && Math.abs(centerPoint.y - y) < 2)
|
||||
topLeftPoint = { x: x + width, y: y - height / 2 }
|
||||
topRightPoint = { x: x + width, y: y + height / 2 }
|
||||
break
|
||||
}
|
||||
|
||||
if (topCell.length === 1) {
|
||||
touchDimension++
|
||||
return
|
||||
}
|
||||
|
||||
leftTopCnt = centerPoints.filter(
|
||||
(centerPoint) => Math.abs(centerPoint.x - topLeftPoint.x) < 2 && Math.abs(centerPoint.y - topLeftPoint.y) < 2,
|
||||
).length
|
||||
rightTopCnt = centerPoints.filter(
|
||||
(centerPoint) => Math.abs(centerPoint.x - topRightPoint.x) < 2 && Math.abs(centerPoint.y - topRightPoint.y) < 2,
|
||||
).length
|
||||
|
||||
if (leftTopCnt + rightTopCnt === 2) {
|
||||
touchDimension++
|
||||
return
|
||||
}
|
||||
|
||||
if (leftTopCnt + rightTopCnt === 1) {
|
||||
exposedHalfTop++
|
||||
halfTouchDimension++
|
||||
return
|
||||
}
|
||||
if (leftTopCnt + rightTopCnt === 0) {
|
||||
exposedTop++
|
||||
}
|
||||
})
|
||||
// 완전 노출 하면 계산
|
||||
|
||||
/*const cells = canvas.getObjects().filter((obj) => polygon.id === obj.parentId)
|
||||
const points = cells.map((cell) => {
|
||||
return cell.getCenterPoint()
|
||||
})*/
|
||||
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 maxYCenterPoint = group.filter((centerPoint) => Math.abs(centerPoint.y - maxY) < 2)
|
||||
let minYCenterPoint = group.filter((centerPoint) => Math.abs(centerPoint.y - minY) < 2)
|
||||
let maxXCenterPoint = group.filter((centerPoint) => Math.abs(centerPoint.x - maxX) < 2)
|
||||
let minXCenterPoint = group.filter((centerPoint) => Math.abs(centerPoint.x - minX) < 2)
|
||||
|
||||
switch (direction) {
|
||||
case 'south':
|
||||
exposedBottom += maxYCenterPoint.length
|
||||
break
|
||||
case 'north':
|
||||
exposedBottom += minYCenterPoint.length
|
||||
break
|
||||
case 'east':
|
||||
exposedBottom += maxXCenterPoint.length
|
||||
break
|
||||
case 'west':
|
||||
exposedBottom += minXCenterPoint.length
|
||||
break
|
||||
}
|
||||
})
|
||||
|
||||
results.push({
|
||||
exposedBottom,
|
||||
exposedHalfBottom,
|
||||
exposedTop,
|
||||
exposedHalfTop,
|
||||
touchDimension,
|
||||
halfTouchDimension,
|
||||
})
|
||||
console.log({
|
||||
direction,
|
||||
exposedBottom,
|
||||
exposedHalfBottom,
|
||||
exposedTop,
|
||||
exposedHalfTop,
|
||||
touchDimension,
|
||||
halfTouchDimension,
|
||||
})
|
||||
})
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
const coordToTurfPolygon = (points) => {
|
||||
const coordinates = points.map((point) => [point.x, point.y])
|
||||
coordinates.push(coordinates[0])
|
||||
|
||||
740
src/hooks/module/useTrestle.js
Normal file
740
src/hooks/module/useTrestle.js
Normal file
@ -0,0 +1,740 @@
|
||||
import { useRecoilValue } from 'recoil'
|
||||
import { canvasState } from '@/store/canvasAtom'
|
||||
import { POLYGON_TYPE } from '@/common/common'
|
||||
import { moduleSelectionDataState } from '@/store/selectedModuleOptions'
|
||||
|
||||
// 회로 및 가대설정
|
||||
export const useTrestle = () => {
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
const moduleSelectionData = useRecoilValue(moduleSelectionDataState) //다음으로 넘어가는 최종 데이터
|
||||
|
||||
const apply = () => {
|
||||
// rack은 맵 형태의 객체인데 key value 형태로 되어있다.
|
||||
// 이때 이 형태를 [{key, value}, ...] 형태로 바꿔야 함.
|
||||
/*const rackInfos = Object.keys(rack).map((key) => {
|
||||
return { key, value: rack[key] }
|
||||
})*/
|
||||
|
||||
//처마력바가 체크되어 있는 경우 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') {
|
||||
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
|
||||
let isEaveBar = construction.setupCover
|
||||
let isSnowGuard = construction.setupSnowCover
|
||||
|
||||
const rack = surface.trestleDetail.rack
|
||||
const { rackQty, rackIntvlPct } = surface.trestleDetail
|
||||
const rackInfos = Object.keys(rack).map((key) => {
|
||||
return { key, value: rack[key] }
|
||||
})
|
||||
|
||||
const result = calculateForApi(surface)
|
||||
const centerPoints = result.centerPoints
|
||||
|
||||
const exposedBottomModules = [] // 아래 두면이 모두 노출 되어있는 경우
|
||||
const leftExposedHalfBottomModules = [] // 왼쪽 면만 노출되어있는 경우
|
||||
const rightExposedHalfBottomPoints = [] // 오른쪽 면만 노출되어 있는 경우
|
||||
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)
|
||||
if (isExposedBottom) {
|
||||
exposedBottomModules.push(module)
|
||||
}
|
||||
if (isLeftExposedHalfBottom) {
|
||||
leftExposedHalfBottomModules.push(module)
|
||||
}
|
||||
if (isRightExposedHalfBottom) {
|
||||
rightExposedHalfBottomPoints.push(module)
|
||||
}
|
||||
})
|
||||
|
||||
canvas
|
||||
.getObjects()
|
||||
.filter((obj) => obj.name === 'eaveBar')
|
||||
.forEach((obj) => {
|
||||
canvas.remove(obj)
|
||||
})
|
||||
|
||||
if (isEaveBar) {
|
||||
// 처마력바설치 true인 경우 설치
|
||||
exposedBottomModules.forEach((module) => {
|
||||
//TODO : 방향별로 처마력바 설치해야함
|
||||
const bottomPoints = findTopTwoPoints([...module.points])
|
||||
if (!bottomPoints) return
|
||||
const eaveBar = new fabric.Line([bottomPoints[0].x, bottomPoints[0].y, bottomPoints[1].x, bottomPoints[1].y], {
|
||||
name: 'eaveBar',
|
||||
stroke: 'blue',
|
||||
strokeWidth: 4,
|
||||
selectable: false,
|
||||
})
|
||||
canvas.add(eaveBar)
|
||||
canvas.renderAll()
|
||||
})
|
||||
}
|
||||
|
||||
// 가대 설치를 위한 가장 아래 모듈로부터 위로 몇단인지 계산
|
||||
// 오른쪽,왼쪽 둘 다 아래에 아무것도 없는, 처마 커버를 필요로 하는 모듈
|
||||
exposedBottomModules.forEach((module) => {
|
||||
const { width, height } = module
|
||||
let { x: startX, y: startY } = { ...module.getCenterPoint() }
|
||||
let { x, y } = { ...module.getCenterPoint() }
|
||||
const direction = 'south'
|
||||
//TODO : 방향별로 가대 설치해야함
|
||||
|
||||
let leftRows = 1
|
||||
let rightRows = 1
|
||||
let centerRows = 1
|
||||
let hasNextModule = true
|
||||
let findLeft = true
|
||||
let findRight = true
|
||||
|
||||
//우선 절반을 나눈 뒤 왼쪽부터 찾는다.
|
||||
while (hasNextModule) {
|
||||
//바로 위에 있는지 확인한다.
|
||||
let nextModule = centerPoints.find((centerPoint) => {
|
||||
return Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y - height)) < 2
|
||||
})
|
||||
|
||||
if (nextModule) {
|
||||
// 바로 위 모듈을 찾는다.
|
||||
leftRows++
|
||||
x = nextModule.x
|
||||
y = nextModule.y
|
||||
} else {
|
||||
// 바로 위가 없을 경우 먼저 왼쪽위가 있는지 확인 한다.
|
||||
if (findLeft) {
|
||||
const topLeftPoint = { x: x - width / 2, y: y - height }
|
||||
nextModule = centerPoints.find((centerPoint) => {
|
||||
return Math.abs(centerPoint.x - topLeftPoint.x) < 2 && Math.abs(centerPoint.y - topLeftPoint.y) < 2
|
||||
})
|
||||
findLeft = false
|
||||
} else {
|
||||
const topRightPoint = { x: x + width / 2, y: y - height }
|
||||
nextModule = centerPoints.find((centerPoint) => {
|
||||
return Math.abs(centerPoint.x - topRightPoint.x) < 2 && Math.abs(centerPoint.y - topRightPoint.y) < 2
|
||||
})
|
||||
findLeft = true
|
||||
}
|
||||
|
||||
if (nextModule) {
|
||||
// 바로 위 모듈을 찾는다.
|
||||
leftRows++
|
||||
x = nextModule.x
|
||||
y = nextModule.y
|
||||
} else {
|
||||
hasNextModule = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hasNextModule = true
|
||||
x = startX
|
||||
y = startY
|
||||
|
||||
// 오른쪽 찾는다.
|
||||
while (hasNextModule) {
|
||||
//바로 위에 있는지 확인한다.
|
||||
let nextModule = centerPoints.find((centerPoint) => {
|
||||
return Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y - height)) < 2
|
||||
})
|
||||
|
||||
if (nextModule) {
|
||||
// 바로 위 모듈을 찾는다.
|
||||
rightRows++
|
||||
x = nextModule.x
|
||||
y = nextModule.y
|
||||
} else {
|
||||
// 바로 위가 없을 경우 먼저 왼쪽위가 있는지 확인 한다.
|
||||
if (findRight) {
|
||||
const topRightPoint = { x: x + width / 2, y: y - height }
|
||||
nextModule = centerPoints.find((centerPoint) => {
|
||||
return Math.abs(centerPoint.x - topRightPoint.x) < 2 && Math.abs(centerPoint.y - topRightPoint.y) < 2
|
||||
})
|
||||
findRight = false
|
||||
} else {
|
||||
const topLeftPoint = { x: x - width / 2, y: y - height }
|
||||
nextModule = centerPoints.find((centerPoint) => {
|
||||
return Math.abs(centerPoint.x - topLeftPoint.x) < 2 && Math.abs(centerPoint.y - topLeftPoint.y) < 2
|
||||
})
|
||||
findRight = true
|
||||
}
|
||||
|
||||
if (nextModule) {
|
||||
// 바로 위 모듈을 찾는다.
|
||||
rightRows++
|
||||
x = nextModule.x
|
||||
y = nextModule.y
|
||||
} else {
|
||||
hasNextModule = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hasNextModule = true
|
||||
x = startX
|
||||
y = startY
|
||||
|
||||
// 센터 찾는다.
|
||||
while (hasNextModule) {
|
||||
//바로 위에 있는지 확인한다.
|
||||
let nextModule = centerPoints.find((centerPoint) => {
|
||||
return Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y - height)) < 2
|
||||
})
|
||||
|
||||
if (nextModule) {
|
||||
// 바로 위 모듈을 찾는다.
|
||||
centerRows++
|
||||
x = nextModule.x
|
||||
y = nextModule.y
|
||||
} else {
|
||||
hasNextModule = false
|
||||
}
|
||||
}
|
||||
|
||||
// 모듈의 왼쪽 부터 그릴 랙 정보를 가져온다.
|
||||
const leftRacks = rackInfos.find((rack) => {
|
||||
return rack.value.moduleRows === leftRows
|
||||
})?.value.racks
|
||||
|
||||
// 모듈의 오른쪽 부터 그릴 랙 정보를 가져온다.
|
||||
const rightRacks = rackInfos.find((rack) => {
|
||||
return rack.value.moduleRows === rightRows
|
||||
})?.value.racks
|
||||
// 해당 rack으로 그려준다.
|
||||
|
||||
const centerRacks = rackInfos.find((rack) => {
|
||||
return rack.value.moduleRows === centerRows
|
||||
})?.value.racks
|
||||
|
||||
drawRacks(leftRacks, rackQty, rackIntvlPct, module, direction, 'L')
|
||||
drawRacks(rightRacks, rackQty, rackIntvlPct, module, direction, 'R')
|
||||
|
||||
if (rackQty === 3) {
|
||||
//rack 갯수가 3개인 경우는 중간렉도 추가해줘야함
|
||||
drawRacks(centerRacks, rackQty, rackIntvlPct, module, direction, 'C')
|
||||
}
|
||||
})
|
||||
// 왼쪽아래에 모듈이 없는 모듈들
|
||||
leftExposedHalfBottomModules.forEach((module) => {
|
||||
const { width, height } = module
|
||||
let { x: startX, y: startY } = { ...module.getCenterPoint() }
|
||||
let { x, y } = { ...module.getCenterPoint() }
|
||||
const direction = 'south'
|
||||
//TODO : 방향별로 가대 설치해야함
|
||||
|
||||
let leftRows = 1
|
||||
let hasNextModule = true
|
||||
let findLeft = true
|
||||
|
||||
//우선 절반을 나눈 뒤 왼쪽부터 찾는다.
|
||||
while (hasNextModule) {
|
||||
//바로 위에 있는지 확인한다.
|
||||
let nextModule = centerPoints.find((centerPoint) => {
|
||||
return Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y - height)) < 2
|
||||
})
|
||||
|
||||
if (nextModule) {
|
||||
// 바로 위 모듈을 찾는다.
|
||||
leftRows++
|
||||
x = nextModule.x
|
||||
y = nextModule.y
|
||||
} else {
|
||||
// 바로 위가 없을 경우 먼저 왼쪽위가 있는지 확인 한다.
|
||||
if (findLeft) {
|
||||
const topLeftPoint = { x: x - width / 2, y: y - height }
|
||||
nextModule = centerPoints.find((centerPoint) => {
|
||||
return Math.abs(centerPoint.x - topLeftPoint.x) < 2 && Math.abs(centerPoint.y - topLeftPoint.y) < 2
|
||||
})
|
||||
findLeft = false
|
||||
} else {
|
||||
const topRightPoint = { x: x + width / 2, y: y - height }
|
||||
nextModule = centerPoints.find((centerPoint) => {
|
||||
return Math.abs(centerPoint.x - topRightPoint.x) < 2 && Math.abs(centerPoint.y - topRightPoint.y) < 2
|
||||
})
|
||||
findLeft = true
|
||||
}
|
||||
|
||||
if (nextModule) {
|
||||
// 바로 위 모듈을 찾는다.
|
||||
leftRows++
|
||||
x = nextModule.x
|
||||
y = nextModule.y
|
||||
} else {
|
||||
hasNextModule = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 모듈의 왼쪽 부터 그릴 랙 정보를 가져온다.
|
||||
const leftRacks = rackInfos.find((rack) => {
|
||||
return rack.value.moduleRows === leftRows
|
||||
})?.value.racks
|
||||
|
||||
drawRacks(leftRacks, rackQty, rackIntvlPct, module, direction, 'L')
|
||||
})
|
||||
// 오른쪽 아래에 모듈이 없는 모듈들
|
||||
rightExposedHalfBottomPoints.forEach((module) => {
|
||||
const { width, height } = module
|
||||
let { x: startX, y: startY } = { ...module.getCenterPoint() }
|
||||
let { x, y } = { ...module.getCenterPoint() }
|
||||
const direction = 'south'
|
||||
//TODO : 방향별로 가대 설치해야함
|
||||
|
||||
let rightRows = 1
|
||||
let hasNextModule = true
|
||||
let findRight = true
|
||||
|
||||
// 오른쪽 찾는다.
|
||||
while (hasNextModule) {
|
||||
//바로 위에 있는지 확인한다.
|
||||
let nextModule = centerPoints.find((centerPoint) => {
|
||||
return Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y - height)) < 2
|
||||
})
|
||||
|
||||
if (nextModule) {
|
||||
// 바로 위 모듈을 찾는다.
|
||||
rightRows++
|
||||
x = nextModule.x
|
||||
y = nextModule.y
|
||||
} else {
|
||||
// 바로 위가 없을 경우 먼저 왼쪽위가 있는지 확인 한다.
|
||||
if (findRight) {
|
||||
const topRightPoint = { x: x + width / 2, y: y - height }
|
||||
nextModule = centerPoints.find((centerPoint) => {
|
||||
return Math.abs(centerPoint.x - topRightPoint.x) < 2 && Math.abs(centerPoint.y - topRightPoint.y) < 2
|
||||
})
|
||||
findRight = false
|
||||
} else {
|
||||
const topLeftPoint = { x: x - width / 2, y: y - height }
|
||||
nextModule = centerPoints.find((centerPoint) => {
|
||||
return Math.abs(centerPoint.x - topLeftPoint.x) < 2 && Math.abs(centerPoint.y - topLeftPoint.y) < 2
|
||||
})
|
||||
findRight = true
|
||||
}
|
||||
|
||||
if (nextModule) {
|
||||
// 바로 위 모듈을 찾는다.
|
||||
rightRows++
|
||||
x = nextModule.x
|
||||
y = nextModule.y
|
||||
} else {
|
||||
hasNextModule = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 모듈의 오른쪽 부터 그릴 랙 정보를 가져온다.
|
||||
const rightRacks = rackInfos.find((rack) => {
|
||||
return rack.value.moduleRows === rightRows
|
||||
})?.value.racks
|
||||
// 해당 rack으로 그려준다.
|
||||
|
||||
drawRacks(rightRacks, rackQty, rackIntvlPct, module, direction, 'R')
|
||||
})
|
||||
})
|
||||
|
||||
/*switch (rackYn) {
|
||||
case 'Y': {
|
||||
// rack이 Y일 경우 rackQty가 필요함
|
||||
|
||||
break
|
||||
}
|
||||
case 'N': {
|
||||
break
|
||||
}
|
||||
}*/
|
||||
// 지지금구 설치
|
||||
installBracket()
|
||||
}
|
||||
|
||||
const drawRacks = (rackInfos, rackQty, rackIntvlPct, module, direction = 'south', l) => {
|
||||
const { width, height } = module
|
||||
|
||||
let startPointX, startPointY
|
||||
|
||||
switch (l) {
|
||||
case 'L': {
|
||||
// 왼쪽부분 시작 점
|
||||
if (direction === 'south') {
|
||||
const x = module.left
|
||||
const y = module.top + module.height / 2
|
||||
startPointX = x + width / rackIntvlPct
|
||||
startPointY = y + height / 2
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
case 'R': {
|
||||
// 오른쪽부분 시작 점
|
||||
if (direction === 'south') {
|
||||
const x = module.left + module.width
|
||||
const y = module.top + module.height / 2
|
||||
startPointX = x - width / rackIntvlPct
|
||||
startPointY = y + height / 2
|
||||
break
|
||||
}
|
||||
}
|
||||
case 'C': {
|
||||
// 중간부분 시작점
|
||||
if (direction === 'south') {
|
||||
startPointX = x
|
||||
startPointY = y + height / 2
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (direction) {
|
||||
case 'south': {
|
||||
rackInfos.forEach((rackInfo) => {
|
||||
const { rackLen, itemId, supFitQty, supFitIntvlPct } = rackInfo
|
||||
|
||||
const rackLength = rackLen / 10
|
||||
|
||||
const rack = new fabric.Line([startPointX, startPointY, startPointX, startPointY - rackLength], {
|
||||
name: 'rack',
|
||||
stroke: 'red',
|
||||
strokeWidth: 4,
|
||||
selectable: false,
|
||||
supFitQty,
|
||||
supFitIntvlPct,
|
||||
rackLen,
|
||||
rackId: itemId,
|
||||
direction: 'top',
|
||||
})
|
||||
|
||||
canvas.add(rack)
|
||||
canvas.renderAll()
|
||||
|
||||
startPointY -= rackLength + 3
|
||||
})
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const installBracket = () => {
|
||||
const racks = canvas.getObjects().filter((obj) => obj.name === 'rack')
|
||||
// name이 bracket인 객체를 찾아서 삭제
|
||||
canvas.getObjects().forEach((obj) => {
|
||||
if (obj.name === 'bracket') {
|
||||
canvas.remove(obj)
|
||||
}
|
||||
})
|
||||
canvas.renderAll()
|
||||
|
||||
racks.forEach((rack) => {
|
||||
const { x1, y1, x2, y2, direction, supFitQty, supFitIntvlPct, rackLen } = rack
|
||||
|
||||
const moduleLength = 10
|
||||
|
||||
if (direction === 'top') {
|
||||
const result = getBracketPoints(supFitQty, supFitIntvlPct)
|
||||
|
||||
result.forEach((percent) => {
|
||||
const bracket = new fabric.Rect({
|
||||
left: x2 - moduleLength / 3,
|
||||
top: y2 + (rackLen / 10) * percent,
|
||||
fill: 'green',
|
||||
name: 'bracket',
|
||||
width: moduleLength,
|
||||
height: moduleLength,
|
||||
selectable: false,
|
||||
})
|
||||
|
||||
canvas.add(bracket)
|
||||
})
|
||||
canvas.renderAll()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getBracketPoints = (n, percent) => {
|
||||
if (n < 2) {
|
||||
throw new Error('Number of points must be at least 2')
|
||||
}
|
||||
|
||||
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) {
|
||||
points.sort((a, b) => b.y - a.y)
|
||||
|
||||
return points.slice(0, 2)
|
||||
}
|
||||
|
||||
const calculateForApi = (moduleSurface) => {
|
||||
const centerPoints = []
|
||||
const direction = moduleSurface.direction
|
||||
const modules = moduleSurface.modules
|
||||
|
||||
modules.forEach((module, index) => {
|
||||
module.tempIndex = index
|
||||
const { x, y } = module.getCenterPoint()
|
||||
const { width, height } = module
|
||||
centerPoints.push({ x, y, width: Math.floor(width), height: Math.floor(height), index })
|
||||
})
|
||||
|
||||
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 = []
|
||||
|
||||
centerPoints.forEach((centerPoint, index) => {
|
||||
const { x, y, width, height } = centerPoint
|
||||
// centerPoints중에 현재 centerPoint와 x값이 같고, y값이 y-height값과 같은 centerPoint가 있는지 확인
|
||||
let bottomCell
|
||||
let bottomLeftPoint
|
||||
let bottomRightPoint
|
||||
let leftBottomCnt
|
||||
let rightBottomCnt
|
||||
|
||||
switch (direction) {
|
||||
case 'south':
|
||||
bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y + height)) < 2)
|
||||
bottomLeftPoint = { x: x - width / 2, y: y + height }
|
||||
bottomRightPoint = { x: x + width / 2, y: y + height }
|
||||
break
|
||||
case 'north':
|
||||
bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y - height)) < 2)
|
||||
bottomLeftPoint = { x: x + width / 2, y: y - height }
|
||||
bottomRightPoint = { x: x - width / 2, y: y - height }
|
||||
break
|
||||
case 'east':
|
||||
bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x - width)) < 2 && Math.abs(centerPoint.y - y) < 2)
|
||||
bottomLeftPoint = { x: x + width, y: y + height / 2 }
|
||||
bottomRightPoint = { x: x + width, y: y - height / 2 }
|
||||
break
|
||||
case 'west':
|
||||
bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x + width)) < 2 && Math.abs(centerPoint.y - y) < 2)
|
||||
bottomLeftPoint = { x: x - width, y: y - height / 2 }
|
||||
bottomRightPoint = { x: x - width, y: y + height / 2 }
|
||||
break
|
||||
}
|
||||
|
||||
if (bottomCell.length === 1) {
|
||||
return
|
||||
}
|
||||
|
||||
// 바로 아래에 셀이 없는 경우 물떼세 배치가 왼쪽 되어있는 셀을 찾는다.
|
||||
leftBottomCnt = centerPoints.filter(
|
||||
(centerPoint) => Math.abs(centerPoint.x - bottomLeftPoint.x) < 2 && Math.abs(centerPoint.y - bottomLeftPoint.y) < 2,
|
||||
).length
|
||||
rightBottomCnt = centerPoints.filter(
|
||||
(centerPoint) => Math.abs(centerPoint.x - bottomRightPoint.x) < 2 && Math.abs(centerPoint.y - bottomRightPoint.y) < 2,
|
||||
).length
|
||||
|
||||
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) => {
|
||||
const { x, y, width, height } = centerPoint
|
||||
|
||||
let topCell
|
||||
let topLeftPoint
|
||||
let topRightPoint
|
||||
let leftTopCnt
|
||||
let rightTopCnt
|
||||
|
||||
switch (direction) {
|
||||
case 'south':
|
||||
topCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y - height)) < 2)
|
||||
topLeftPoint = { x: x - width / 2, y: y - height }
|
||||
topRightPoint = { x: x + width / 2, y: y - height }
|
||||
break
|
||||
case 'north':
|
||||
topCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y + height)) < 2)
|
||||
topLeftPoint = { x: x + width / 2, y: y + height }
|
||||
topRightPoint = { x: x - width / 2, y: y + height }
|
||||
break
|
||||
case 'east':
|
||||
topCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x - width)) < 2 && Math.abs(centerPoint.y - y) < 2)
|
||||
topLeftPoint = { x: x - width, y: y + height / 2 }
|
||||
topRightPoint = { x: x - width, y: y - height / 2 }
|
||||
break
|
||||
case 'west':
|
||||
topCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x + width)) < 2 && Math.abs(centerPoint.y - y) < 2)
|
||||
topLeftPoint = { x: x + width, y: y - height / 2 }
|
||||
topRightPoint = { x: x + width, y: y + height / 2 }
|
||||
break
|
||||
}
|
||||
|
||||
if (topCell.length === 1) {
|
||||
touchDimension++
|
||||
return
|
||||
}
|
||||
|
||||
leftTopCnt = centerPoints.filter(
|
||||
(centerPoint) => Math.abs(centerPoint.x - topLeftPoint.x) < 2 && Math.abs(centerPoint.y - topLeftPoint.y) < 2,
|
||||
).length
|
||||
rightTopCnt = centerPoints.filter(
|
||||
(centerPoint) => Math.abs(centerPoint.x - topRightPoint.x) < 2 && Math.abs(centerPoint.y - topRightPoint.y) < 2,
|
||||
).length
|
||||
|
||||
if (leftTopCnt + rightTopCnt === 2) {
|
||||
touchDimension++
|
||||
return
|
||||
}
|
||||
|
||||
if (leftTopCnt + rightTopCnt === 1) {
|
||||
exposedHalfTop++
|
||||
halfTouchDimension++
|
||||
return
|
||||
}
|
||||
if (leftTopCnt + rightTopCnt === 0) {
|
||||
exposedTop++
|
||||
}
|
||||
})
|
||||
// 완전 노출 하면 계산
|
||||
|
||||
/*const cells = canvas.getObjects().filter((obj) => polygon.id === obj.parentId)
|
||||
const points = cells.map((cell) => {
|
||||
return cell.getCenterPoint()
|
||||
})*/
|
||||
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,
|
||||
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
|
||||
}
|
||||
|
||||
return { apply }
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user