Files
cut-abstractions/tests/dev1/dataHandle/common/LayoutEngine/BlockDoFace.ts

366 lines
11 KiB
TypeScript
Raw Normal View History

2025-07-22 18:22:31 +08:00
import { BlockHelper } from './BlockHelper.js'
import { BlockSizePlus } from './BlockSizePlus.js'
import { resetPlaceBoard } from './PlaceBase.js'
import { NcCustomized } from '@/imes/biz/NcCustomized.js'
import { FaceType, HoleType, HoleArrange, PlaceBlock, PlaceMaterial, PlaceBoard } from '../../confClass.js'
/** 计算大板中所有的小板的正反面孔造型数量,让正面加工时间接近 比例 30% */
export async function TurnOverWithDoneRate(pm: PlaceMaterial, cncData: boolean, doneRate: number, sp_h: number, sp_m: number) {
let i = 0
console.time(`${pm.fullName} full use time`)
for (let pb of pm.boardList) {
// if (pb.IsOddmengt) continue;
i++
// console.log(`${pm.FullName} bid=${i} 开始计算`);
await TurnOverWithDoneRate_pb(pm, pb, cncData, doneRate, sp_h, sp_m, i)
}
console.timeEnd(`${pm.fullName} full use time`)
}
/** 计算大板中所有的小板的正反面孔造型数量,让正面加工时间接近 比例 30% */
export async function TurnOverWithDoneRate_pb(pm: PlaceMaterial, pb: PlaceBoard, useCncData: boolean, doneRate: number, sp_h: number, sp2: number, i) {
// 孔 0.5秒/个
// 造型, 16秒/米 , 0.016秒/mm
let sp_m = sp2 * 0.001
let rate = doneRate * 0.01
// 一. 先求出大板所有小板,当前正反面加工时间,是否可翻转
let tm: any = [] //
let t1_z = 0 // 不可翻 正面加工时间 合计
let t1_f = 0 // 不可翻 反面加工时间 合计
let t2_z = 0 // 可翻 正面加工时间 合计
let t2_f = 0 // 可翻 反面加工时间 合计
let t_full = 0 // 所有加工时间 合计
let t_throngh = 0// 挖穿的造型的时间,
for (let block of pb.blockList) {
let tc = 0 // 挖穿;
let tz = 0 // 当前加工面 时间
let tf = 0 // 反面 时间
let holes = block.holeListFaceA
let models = block.modelListFaceA
if (useCncData) // 使用cnc 数据
{
holes = block.isTurnOver ? block.holeListOrgFaceB.filter(t => t.isCutting == false) : block.holeListOrgFaceA.filter(t => t.isCutting == false)
models = block.isTurnOver ? block.modelListOrgFaceB.filter(t => t.isCutting == false) : block.modelListOrgFaceA.filter(t => t.isCutting == false)
}
tz += holes.length * sp_h // 正面孔时间
for (let model of models) {
let len = 0
for (let i = 0; i < model.pointList.length - 1; i++) {
let p0 = model.pointList[i]
let p1 = model.pointList[i + 1]
if (p0 == null || p1 == null)
continue
len += Math.sqrt((p0.pointX - p1.pointX) ** 2 + (p0.pointY - p1.pointY) ** 2)
}
if (model.depth >= block.thickness - 0.001) {
tc += len * sp_m
}
else {
tz += len * sp_m
}
}
let holes2 = block.holeListFaceB
let models2 = block.modelListFaceB
if (useCncData) // 使用cnc 数据
{
holes2 = block.isTurnOver ? block.holeListOrgFaceA.filter(t => t.isCutting == false) : block.holeListOrgFaceB.filter(t => t.isCutting == false)
models2 = block.isTurnOver ? block.modelListOrgFaceB.filter(t => t.isCutting == false) : block.modelListOrgFaceB.filter(t => t.isCutting == false)
}
tf += holes2.length * sp_h
for (let model of models2) {
let len = 0
for (let i = 0; i < model.pointList.length - 1; i++) {
let p0 = model.pointList[i]
let p1 = model.pointList[i + 1]
if (p0 == null || p1 == null)
continue
len += Math.sqrt((p0.pointX - p1.pointX) ** 2 + (p0.pointY - p1.pointY) ** 2)
}
tf += len * sp_m
}
if (tz + tc == 0 && tf == 0)
continue // 没有加工
let canTurn = true
if (block.isUnRegular)
canTurn = false // 异形不能翻
if (canTurn && block.placeHole != 2)
canTurn = false // 非可翻转的
if (canTurn && hasChildBlock(block, pb.blockList))
canTurn = false// 里面有小板,不能翻
t_throngh += tc
t_full += (tc + tz + tf)
if (canTurn == false) // 不能翻
{
t1_z += tz
t1_f += tf
}
else // 可以翻 ,
{
if (Math.abs(tz - tf) > sp_h) // 翻面效果很差, 时间小于一个孔 ,翻不翻无所谓,
{
tm.push({ bno: block.blockNo, z: tz, f: tf, dis: tz - tf, child: [] })
}
t2_z += tz
t2_f += tf
}
}
// 二. 计算 不可翻的小板 正面加工 与理论值 相差多少
let t2_L = t_full * rate - t1_z - t_throngh // 剩下加工正面的时间 理论值 ( 理论值- 当前正面加工时间,就是剩下可翻的板 正面加工时间 )
let tz: any = t1_z + t_throngh + t2_z // 当前正面时间
let t2_dis = t2_z - t2_L // 理论值与 当前剩下正面加工时间的差值 ,应该要节省的时间总
// 正面加工时间 比例 接近预定于的比例 。 则不再计算
if (Math.abs(100 * t2_dis / t_full) < 3)
return { tz, fz: t_full - tz, full: t_full }
// 三.接下来的问题就是在 tm 中 找出 翻面加工省时 合计 最接近 t2_dis 的集合出来.
let best_list: any = [] // 最优解 需要翻面的
let best_v = t2_dis // 差值最大 默认当前
// 四.将tm 转换成 最多16个可翻面 的数组
tm.sort((a, b) => a.dis - b.dis) // 按小到大排序
// 精简 tm //将tm中 翻面效果 相反的 且大的 剔除掉
if (tm.length > 16) {
if (t2_dis > 0) {
for (let i = tm.length - 1; i >= 0; i--) {
if (tm[i].dis < -t2_dis) {
tm.splice(i, 1)
}
}
}
else {
for (let i = tm.length - 1; i >= 0; i--) {
if (tm[i].dis > -t2_dis) {
tm.splice(i, 1)
}
}
}
}
if (tm.length == 0)
return { tz, fz: t_full - tz, full: t_full }
let blocks: any = []
for (let b of pb.blockList) {
blocks[b.blockNo] = b
}
// 可翻转小板集合,精简
tm = smallerBlocks(tm)
let rt = await getBestTurnBlocks(pm, i, tm, best_v, t_full)
best_list = rt.result
best_v = rt.v
// 四. 将最优解中的小板 翻面
for (let m of best_list) {
tz -= m.dis
let bs: any = []
let block: any = blocks[m.bno]
bs.push(block)
for (let no of m.child) {
bs.push(blocks[no])
}
for (let block of bs) {
let orgStyle = block.placeStyle
let newStyle = BlockHelper.getTurnedPlaceStyle(orgStyle, 0)
let orgPlaceX = block.placeX - block.placeOffX
let orgPlaceY = block.placeY - block.placeOffY
let offset = BlockSizePlus.getOffDis(block, newStyle)
let newPlaceX = orgPlaceX + offset.x
let newPlaceY = orgPlaceY + offset.y
block.placeX = newPlaceX
block.placeY = newPlaceY
block.placeOffX = offset.x
block.placeOffY = offset.y
// 修改小板的放置方式
BlockHelper.resetPlaceStyle(block, newStyle)
}
}
// 重设pb
if (best_list.length > 0)
resetPlaceBoard(pm, pb)
return { tz, fz: t_full - tz, full: t_full }
}
/** 获取加工面processMode: 0开料机加工 1开料机CNC组合加工 2定制加工 */
export function 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 getHoleFaceMore(block)
}
// 造型单面 作为开料面
if (block.modelCountFront() > 0 && block.modelCountBack() == 0)
return true
if (block.modelCountFront() == 0 && block.modelCountBack() > 0)
return false
return true
}
/** 大孔/孔多作为正面 */
function getHoleFaceMore(block: PlaceBlock): boolean {
if (!block.blockDetail) {
console.log('getHoleFaceMore: blockDetail is undefind', block)
return true
}
// 优先考虑 大孔面
let bigHole = block.blockDetail.holes.find(t => t.holeType == HoleType.BIG_HOLE)
if (bigHole)
return bigHole.face == FaceType.FRONT
// 多孔面
if (block.blockDetail.holeListFaceA.length > block.blockDetail.holeListFaceB.length)
return true
if (block.blockDetail.holeListFaceA.length < block.blockDetail.holeListFaceB.length)
return false
return true
}
// 大孔/孔多 作为正面
function getHoleFace_more(block: PlaceBlock): boolean {
// 优先考虑 大孔面
let bigHole = block.holes().find(t => t.holeType == HoleType.BIG_HOLE)
if (bigHole)
return bigHole.face == FaceType.FRONT
// 多孔面
if (block.holeCountFront > block.holeCountBack)
return true
if (block.holeCountFront < block.holeCountBack)
return false
return true
}
// 非大孔/孔少 作为正面
function getHoleFace_less(block: PlaceBlock): boolean {
// 优先考虑 大孔面
let bigHole = block.holes().find(t => t.holeType == HoleType.BIG_HOLE)
if (bigHole)
return bigHole.face != FaceType.FRONT
// 少孔面
if (block.holeCountFront > block.holeCountBack)
return false
if (block.holeCountFront < block.holeCountBack)
return true
return true
}
// 可翻转小板集合,精简
function smallerBlocks(tm: any[]): any[] {
if (tm.length <= 30)
return tm
let time = 1
if (tm.length > 40)
time = 2
if (tm.length > 60)
time = 3
if (tm.length > 80)
time = 4
if (tm.length > 100)
time = 5
if (tm.length > 120)
time = 10
let newtm: any = []
let newLength = Math.ceil(tm.length / time)
for (let t = 0; t < newLength; t++) {
let block0 = tm[t * time]
block0.child = [] // bno: block.BlockNo, z: t1, f: t2, dis: t1 - t2
for (let i = 1; i < time; i++) {
let j = t * time + i
if (j >= tm.length)
break
let blockNext = tm[j]
block0.child.push(blockNext.bno)
block0.z += blockNext.z
block0.f += blockNext.f
block0.dis += blockNext.dis
}
newtm.push(block0)
}
return newtm
}
async function getBestTurnBlocks(pm, pid, tm: any[], best_v, t_full) {
let result = []
let result_v = best_v
let disRate = 111111
return new Promise<any>((resolve, reject) => {
let num1 = 1
let num2 = 2 ** tm.length - 1
let isOK = false
// const worker = new Worker(new URL('./FaceDoTimeWorker', import.meta.url))
// worker.onmessage = (res) =>
// {
// let tmp = res.data.tmp
// let v = res.data.v
// let rate = res.data.rate
// result = tmp
// result_v = v
// disRate = rate
// if (res.data.ok == 1)
// {
// worker.terminate() // 关闭
// resolve({ result, v: result_v })
// isOK = true
// }
// }
// worker.postMessage({ num1, num2, blocks: tm, disTime: best_v, fullTime: t_full })
// Sleep(3000).then(() =>
// {
// if (isOK)
// return
// resolve({ result, v: result_v })
// // console.log(`${pm.FullName} bid=${pid} ${tm.length} 超时3秒`);
// })
})
}
/** 判断block 里头有没有小板 */
function hasChildBlock(block: PlaceBlock, blocks: PlaceBlock[]): boolean {
for (let b of blocks) {
if (b.blockNo == block.blockNo)
continue
if (b.placeX > block.placeX && b.placeX + b.placeWidth < block.placeX + block.placeWidth && b.placeY > block.placeY && b.placeY + b.placeLength < block.placeY + block.placeLength)
return true
}
return false
}