284 lines
9.5 KiB
TypeScript
284 lines
9.5 KiB
TypeScript
|
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
|
|||
|
}
|
|||
|
}
|