Files
cut-abstractions/tests/dev1/dataHandle/common/LayoutEngine/BlockDoFace.ts
2025-07-22 18:22:31 +08:00

366 lines
11 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}