import { ConfigBase } from "../../src/models/config"; import { confItem, HoleArrange, Knife, PlaceBlock, PlaceBlockDetail, PlaceMaterial } from "../confClass"; import { Big_bang, ComposingType, LineType, WorkerItemType, xbang } from "../handleAbility/RectOptimizeWorker/bang"; /** 配置列表 */ export const confList: confItem[] = [ { key: 'isCutProcess', label: '开料机(雕刻机)加工', value: true }, { key: 'isCutAndCNCProcess', label: '开料机CNC组合', value: false }, { key: 'isCustomized', label: '定制加工', value: false }, { key: 'cutBoardBorder', label: '总修边宽度', value: 3 }, { key: 'blockKnifeLineSpacing', label: '刀路间距', value: 0 }, { key: 'isDoubleFaceBlockFirst', label: '双面开料优先排版', value: true }, { key: 'isRectPlace', label: '新优化规则排版', value: false }, { // yuLiaoBoardDo2FaceBlock key: 'isDoubleFaceBlockInRemain', label: '余料板允许排入双面加工的小板', value: true }, ] /** * 新优化 * 调用流程 * 1、准备工作 加载配置 + 加载刀库 + 设置 回调函数 * 2、调用 startPlaceThreed * 入参:data (数据源 必须包含 小板数据列表和小板明细数据列表) * pm 优化的材质 * pm.diameter = knife?.diameter pm.cutKnifeName = knife.knifeName */ export class BusinessRectOptimizeMachine extends ConfigBase { /** 多线程数据集 */ workerList: WorkerItemType[] = [] /** 优化回调 */ placeCallBack: Function = () => { } constructor() { super() } /** 设置优化回调 */ setPlaceTaskCallBackFun(func: Function) { this.placeCallBack = func } /**开始优化线程 输入的数据没有初始化 * @param data 数据源 包含小板列表和小板明细列表 data内需要包含blockList(小板列表) 和 blockDetailList(小板明细列表) * @param pm 优化的材质 包含该材质的可用开料大板信息 需包含开料刀的信息 pm.diameter pm.cutKnifeName */ startPlaceThreed(data, pm: PlaceMaterial) { let { blockList, blockDetailList } = data let bList: any = [] blockList.map(e => { if (e.goodsId == pm.goodsId) { bList[e.blockNo] = e let detail = blockDetailList.find(x => x.blockId == e.blockId) if (!Reflect.has(bList[e.blockNo], 'blockDetail')) { bList[e.blockNo].blockDetail = new PlaceBlockDetail(detail) } // bList[e.blockNo].isTurnFaceToPlace = !this.getDoFace(bList[e.blockNo], this.processMode()) // 是否翻面后续处理 bList[e.blockNo].isTurnFaceToPlace = true pm.blockList.push(e) } }) pm.cutBorder = this.cutBoardBorder pm.cutKnifeGap = this.blockKnifeLineSpacing /** 小板 */ let bans: xbang[] = [] // 实际开料大板的列表 let big_Bang: Big_bang[] = [] let big_BangSL: number[] = [] let border = this.cutBoardBorder let borderOff = (pm.diameter + pm.cutKnifeGap) / 2 // 余料板 以及实际开料大板 for (const cuttingBoard of pm.remainBoardList) { big_Bang.push({ w: cuttingBoard.width - border * 2 + borderOff * 2, l: cuttingBoard.length - border * 2 + borderOff * 2, x: border - borderOff, y: border - borderOff }) big_BangSL.push(cuttingBoard.count || 999) } // big_Bang = [] // big_BangSL = [] // 母板 兜底的 big_Bang.push({ w: pm.width - border * 2 + borderOff * 2, l: pm.length - border * 2 + borderOff * 2, x: border - borderOff, y: border - borderOff }) // 生成小板 for (let key in bList) { let b = bList[key] let bid = b.blockNo let width = b.placeFullWidth let length = b.placeFullLength let line = this.toLine(b.texture) bans.push({ l: length, w: width, line, face: this.toface(b), id: bid, bno: b.blockNo, holeFaceCount: 3, isRect: !b.isUnRegular, hasHole: false, isdtwosided: true, }) } let bestCount = 0 if (bans.length == 0) // 没有板了 { let best = [] let yl: Big_bang[] = [] let fit = 0 let resObj = { data: { bList, best, yl, fit, bans, width: pm.width, length: pm.length, bestCount: bestCount++, pm }, info: { times: -1, type: 'noBan' } } this.placeCallBack(resObj) return } let xyhcs = 50 if (bans.length > 1000) { xyhcs = 40 } else if (bans.length > 1500) { xyhcs = 30 } else if (bans.length > 2000) { xyhcs = 25 } else if (bans.length > 4000) { xyhcs = 20 } else if (bans.length > 6000) { xyhcs = 15 } else if (bans.length > 10000) { xyhcs = 10 } else if (bans.length > 15000) { xyhcs = 5 } else if (bans.length > 20000) { xyhcs = 1 } let isDoubleFaceBlockFirst = this.isDoubleFaceBlockFirst // 双面加工排前面 let gap = this.blockKnifeLineSpacing // this.bestfit = 0 for (let j = 0; j < 1; j++) { let w = new Worker(new URL('../handleAbility/RectOptimizeWorker/RectOptimizeWorker.worker', import.meta.url), { type: 'module' }) const data = { type: 'start', data: [bans, big_Bang, big_BangSL, xyhcs, isDoubleFaceBlockFirst, gap, this.isRectPlace, this.isDoubleFaceBlockInRemain], } let item: WorkerItemType = { w: w, goodsId: pm.goodsId, pm, status: 'start' } if (this.workerList.findIndex(e => e.goodsId == item.goodsId) == -1) { this.workerList.push(item) } let workItem = this.workerList.find(e => e.goodsId == pm.goodsId) if (workItem && workItem != undefined) { workItem.w?.postMessage(data) workItem.w.onmessage = async (d) => { let [best, yl, fit, info] = d.data as [any[], Big_bang[], number, any] switch (info.type) { case 'loop': let resObj = { data: { bList, best, yl, fit, bans, width: pm.width, length: pm.length, bestCount: bestCount++, pm }, info } this.placeCallBack(resObj) break; case 'stop': console.error('stop =》dataHandleBase', info, this.workerList) this.terminateWorker({ goodsId: pm.goodsId }) break; case 'isStop': // console.error('isStop', info) break; default: break; } } } console.log('新算法线程启动', pm.goodsId, this.workerList) } } /** 停止优化 */ async stopPlaceTask() { for (const key in this.workerList) { await this.terminateWorker({ key }) } } /** * 获取加工面 * @param block * @param processMode * @returns */ getDoFace(block: PlaceBlock, processMode: number = 0): boolean { // 模式0: 开料机处理排钻, 造型, 采用大孔面作为正面的模式. 正面多加工, cnc多加工 if (processMode == 0) { // 先考虑 设计开料面 if (block.placeHole == HoleArrange.FRONT) return true if (block.placeHole == HoleArrange.BACK) return false // 造型单面 作为开料面 if (block.modelCountFront() > 0 && block.modelCountBack() == 0) return true if (block.modelCountFront() == 0 && block.modelCountBack() > 0) return false // 优先考虑 大孔面 多孔面 return this.getHoleFaceMore(block) } else { return false } } processMode() { let processMode = 0; if (this.isCutProcess) processMode = 0; if (this.isCutAndCNCProcess) processMode = 1; if (this.isCustomized) processMode = 2; return processMode; } /** * 正纹 = 0, 可翻转 = 1, 反纹 = 2; * 正文 Positive = 0, 反纹 Reverse = 1, 可翻转 CanReversal = 2, */ toLine(texture): LineType { if (texture == 0) return LineType.Positive if (texture == 1) return LineType.CanReversal return LineType.Reverse } /** 小板加工面:Positive=0正面 Reverse=1反面 Arbitrary=2任意 */ toface(block: PlaceBlock): ComposingType { let turnF = block.isTurnFaceToPlace if (this.isTurnFaceToPlace) turnF = !turnF if (!turnF) return ComposingType.Positive return ComposingType.Reverse } }