2025-07-22 18:22:31 +08:00
|
|
|
|
<script lang="ts" setup>
|
|
|
|
|
import { ref, onMounted, computed } from 'vue'
|
|
|
|
|
import { nextTick } from 'vue'
|
|
|
|
|
import BoardView from '@/components/borderView/BoardView.vue'
|
|
|
|
|
import {
|
|
|
|
|
Select, SelectOption, Pagination, TreeSelect, Form, FormItem,
|
|
|
|
|
Input, Button, Table, Modal, Textarea, Tooltip, Switch,
|
|
|
|
|
InputNumber, Checkbox
|
|
|
|
|
} from 'ant-design-vue'
|
|
|
|
|
|
|
|
|
|
import { Knife, SysConfig } from '@/imes/biz/SysConfig'
|
|
|
|
|
import { ParserMain } from '@/imes/processParser/parseMain'
|
|
|
|
|
import { PlusOutlined } from '@ant-design/icons-vue'
|
|
|
|
|
import { getListAllSimple, getOrderSource } from '@/api/production/productManagerList'
|
|
|
|
|
import { BoardShowType } from '@/imes/vo/enums/BoardShowType'
|
|
|
|
|
|
|
|
|
|
import { BlockBorderPoint } from '@/imes/vo/point/BlockBorderPoint'
|
|
|
|
|
import { BoardEditor } from '@/imes/biz/RenderNewBoard'
|
|
|
|
|
import { BasicTable, TableAction, useTable } from '@/components/Table'
|
|
|
|
|
import { optimizeColumns1 } from '../production/productManagerList/productManagerList.data'
|
|
|
|
|
import { DataHandleServe } from '@/imes/dataHandle/DataHandleServe'
|
|
|
|
|
import { convertData } from '@/imes/common/transform'
|
|
|
|
|
import { blockborderClass } from '@/imes/dataClass/blockborderClass'
|
|
|
|
|
import { Arc2d, Curve2d } from '@/imes/common/base/CAD'
|
|
|
|
|
import { ProcessorContext } from './dataHandle/base'
|
|
|
|
|
import { OptimizeLayoutProcessor } from './dataHandle/optimizeLayout/optimizeLayout'
|
|
|
|
|
import { ToolsHelper } from './dataHandle/tools/tool'
|
|
|
|
|
import {
|
|
|
|
|
BlockPlaceResult, BoardPlaceResult, BoardPosition, MaterialPlaceResult, PlaceBoard, PlaceStyle,
|
|
|
|
|
PlaceBlock, PlaceBlockDetail,
|
|
|
|
|
PlaceMaterial, RemainBlock,
|
|
|
|
|
PlacePositionClass,
|
|
|
|
|
CodeParams,
|
|
|
|
|
BlockHole,
|
|
|
|
|
BlockModel,
|
|
|
|
|
BlockModelPoint
|
|
|
|
|
} from './dataHandle/confClass'
|
|
|
|
|
import { BlockSizePlus } from './dataHandle/common/LayoutEngine/BlockSizePlus'
|
|
|
|
|
import { Point } from './dataHandle/common/Vector2'
|
|
|
|
|
import { PlacePositionHelper } from './dataHandle/common/PlacePostionHelper'
|
|
|
|
|
import { DisPoseModelInBoardBorder } from './dataHandle/common/LayoutEngine/DisposeModelInBoardBorder'
|
|
|
|
|
import { getMaterialSealEdge } from './dataHandle/common/BlockSealEdge'
|
|
|
|
|
import { ArrayExt } from './dataHandle/ArrayExt'
|
|
|
|
|
import { CutOrder } from './dataHandle/common/cutorder/CutOrder'
|
|
|
|
|
import { CutPointHelper } from './dataHandle/common/cutorder/CutPointHelper'
|
|
|
|
|
import { CodeParamsList, CodeParamsObj } from '@/imes/processParser/confClass'
|
|
|
|
|
import { BlockHelper } from './dataHandle/common/LayoutEngine/BlockHelper'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const selectedMachineID = ref() // 机台选中
|
|
|
|
|
const machineList = ref<any>([]) // 机台列表
|
|
|
|
|
// 1920321997498220544 1907276351086264320 1920401449485860864 1920739893772812288
|
|
|
|
|
const orderNo = ref('1920401449485860864')
|
|
|
|
|
const canvasWidth = ref(1200)
|
|
|
|
|
const canvasHeight = ref(650)
|
|
|
|
|
const paginationCurrent = ref<any>(1)
|
2025-07-23 10:12:11 +08:00
|
|
|
|
const paginationCurrentAll = ref<any>(1)
|
2025-07-22 18:22:31 +08:00
|
|
|
|
const boardEditor = ref<BoardEditor>()
|
|
|
|
|
const canvasMain = ref()
|
|
|
|
|
const canvas = ref()
|
|
|
|
|
const isOptimizeing = ref(false)
|
|
|
|
|
const _handleServe = ref<OptimizeLayoutProcessor | null>(null)
|
|
|
|
|
const selectVal = ref<any>()
|
|
|
|
|
const plateSelectOptions = ref<any>([])
|
|
|
|
|
const parserMain = ref<ParserMain>(new ParserMain())
|
2025-07-23 10:12:11 +08:00
|
|
|
|
const testData1 = ref('')
|
2025-07-22 18:22:31 +08:00
|
|
|
|
const dataBase = ref<any>(null)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 添加显示标志位数组,用于记录当前需要绘制的内容
|
|
|
|
|
const displayFlags = ref({
|
|
|
|
|
isLockd: false, // 是否锁定
|
|
|
|
|
showBlocks: false, // 是否显示小板
|
|
|
|
|
showCutPoints: false, // 是否显示下刀点
|
|
|
|
|
showCutOrders: false, // 是否显示开料顺序
|
|
|
|
|
showCutNo: false, // 是否显示板号
|
|
|
|
|
showCutArrow: false, // 是否显示开料方向箭头
|
|
|
|
|
showManualPlace: false, // 是否显示手动排版
|
|
|
|
|
showHoles: false, // 是否显示孔洞
|
|
|
|
|
showModels: false, // 是否显示造型
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 初始化解析器
|
|
|
|
|
parserMain.value.setDeviceByKey('device1')
|
|
|
|
|
|
|
|
|
|
// 画布控制器
|
|
|
|
|
const canvasController = ref({
|
|
|
|
|
showType: BoardShowType.NORMAL,
|
|
|
|
|
showHelpCut: false,
|
|
|
|
|
isDragingBlock: false,
|
|
|
|
|
clickedBlock: new PlaceBlock(),
|
|
|
|
|
clickedScrapBlock: new RemainBlock(1, 1, 100, 100),
|
|
|
|
|
dragedDistance: Point,
|
|
|
|
|
beginDragPosition: Point,
|
|
|
|
|
mousePostion: Point,
|
|
|
|
|
dragingBlockPoint: BlockBorderPoint,
|
|
|
|
|
closestBlockPoint: BlockBorderPoint
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const currentMaterial = computed(() => {
|
|
|
|
|
if (!dataBase.value?.materialList) return null;
|
|
|
|
|
const mIndex = dataBase.value.materialList.findIndex(e => e.goodsId === selectVal.value);
|
|
|
|
|
return mIndex >= 0 ? dataBase.value.materialList[mIndex] : null;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const currentBoard = computed(() => {
|
|
|
|
|
if (!currentMaterial.value?.boardList) return null;
|
|
|
|
|
const pIndex = paginationCurrent.value - 1;
|
|
|
|
|
return pIndex >= 0 && pIndex < currentMaterial.value.boardList.length
|
|
|
|
|
? currentMaterial.value.boardList[pIndex]
|
|
|
|
|
: null;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
getOptions();
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const [registerTable, { setTableData, updateTableData, getDataSource }] = useTable({
|
|
|
|
|
title: '',
|
|
|
|
|
columns: optimizeColumns1,
|
|
|
|
|
useSearchForm: false,
|
|
|
|
|
rowKey: 'id',
|
|
|
|
|
pagination: false,
|
|
|
|
|
canResize: true,
|
|
|
|
|
maxHeight: 100,
|
|
|
|
|
showTableSetting: false,
|
|
|
|
|
actionColumn: {}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取弹出容器
|
|
|
|
|
*/
|
|
|
|
|
function getPopupContainer(node?: HTMLElement): HTMLElement {
|
|
|
|
|
return (node?.parentNode as HTMLElement) ?? document.body
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取机台列表
|
|
|
|
|
*/
|
|
|
|
|
async function getOptions() {
|
|
|
|
|
const res = await getListAllSimple({ type: 1 });
|
|
|
|
|
if (res) {
|
|
|
|
|
machineList.value = res;
|
|
|
|
|
selectedMachineID.value = res[0].id;
|
|
|
|
|
_getPlaceOrderData();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 订单变化处理
|
|
|
|
|
*/
|
|
|
|
|
function orderNoChange() {
|
|
|
|
|
_getPlaceOrderData();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 机台变化处理
|
|
|
|
|
*/
|
|
|
|
|
function machineChange() {
|
|
|
|
|
// 机台变化逻辑
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取排版订单数据
|
|
|
|
|
*/
|
|
|
|
|
async function _getPlaceOrderData() {
|
|
|
|
|
const params = {
|
|
|
|
|
// orderId: '1792854086534561792',
|
|
|
|
|
// machineId: '14193',
|
|
|
|
|
orderId: orderNo.value,
|
|
|
|
|
machineId: selectedMachineID.value,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const res = await getOrderSource(params);
|
|
|
|
|
if (!res) return;
|
|
|
|
|
|
|
|
|
|
let conf = JSON.parse(res.machineDTO.setting);
|
|
|
|
|
let tempData = { ...res, optimizeBoardModelDOS: [] };
|
|
|
|
|
let newGoodsList: any[] = [];
|
|
|
|
|
for (let material of tempData.goodsList) {
|
|
|
|
|
if (material.height == 0) material.height = 2440;
|
|
|
|
|
if (material.width == 0) material.width = 1220;
|
|
|
|
|
|
|
|
|
|
if (newGoodsList.findIndex(e => e.goodsId == material.goodsId) == -1) {
|
|
|
|
|
newGoodsList.push(material);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tempData.goodsList = newGoodsList;
|
|
|
|
|
|
|
|
|
|
let newTestData = convertData(tempData);
|
|
|
|
|
let goodsId = newTestData.materialList.map(e => e.goodsId)[0]
|
|
|
|
|
|
|
|
|
|
newTestData.blockList.forEach(block => {
|
|
|
|
|
block.goodsId = goodsId
|
|
|
|
|
});
|
|
|
|
|
dataBase.value = newTestData;
|
|
|
|
|
|
|
|
|
|
let sysConfig = new SysConfig(conf);
|
|
|
|
|
let _sysConfig = { ...sysConfig };
|
|
|
|
|
|
|
|
|
|
setTableData(newTestData.materialList);
|
|
|
|
|
selectVal.value = newTestData.materialList[0].goodsId;
|
|
|
|
|
plateSelectOptions.value = newTestData.materialList;
|
|
|
|
|
_sysConfig.boardBorder = _sysConfig.cutBoardBorder;
|
|
|
|
|
|
|
|
|
|
let eleCanvasMain = document.getElementsByClassName('contentMain')[0];
|
|
|
|
|
const { clientWidth, clientHeight } = eleCanvasMain;
|
|
|
|
|
canvasWidth.value = clientWidth - 10;
|
|
|
|
|
canvasHeight.value = clientHeight - 30;
|
|
|
|
|
|
|
|
|
|
await nextTick();
|
|
|
|
|
boardEditor.value = new BoardEditor(
|
|
|
|
|
canvas.value.canvasRef,
|
|
|
|
|
_sysConfig,
|
|
|
|
|
canvasController.value
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
boardEditor.value.boardWidth = sysConfig.boardWidth;
|
|
|
|
|
boardEditor.value.boardLength = sysConfig.boardLength;
|
|
|
|
|
boardEditor.value.drawBase();
|
|
|
|
|
boardEditor.value.setSysConfig(_sysConfig);
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-23 10:12:11 +08:00
|
|
|
|
|
2025-07-22 18:22:31 +08:00
|
|
|
|
async function initHandleServe1() {
|
|
|
|
|
|
|
|
|
|
let newTestData = dataBase.value;
|
|
|
|
|
//#region 刀库
|
|
|
|
|
let toolsHelperClass = new ToolsHelper();
|
|
|
|
|
let contextKnife: ProcessorContext<Knife[], any, any> = {
|
|
|
|
|
input: newTestData.sysConfig.knifeList,
|
|
|
|
|
output: {},
|
|
|
|
|
params: newTestData.sysConfig
|
|
|
|
|
}
|
|
|
|
|
const toolsHelper = toolsHelperClass.exec(contextKnife)
|
|
|
|
|
//#endregion
|
|
|
|
|
|
|
|
|
|
//#region 优化排版
|
|
|
|
|
let input = {
|
|
|
|
|
materialList: newTestData.materialList,
|
|
|
|
|
blockList: newTestData.blockList,
|
|
|
|
|
blockDetailList: newTestData.blockDetailList,
|
|
|
|
|
toolsHelper: toolsHelper,
|
|
|
|
|
}
|
|
|
|
|
let params = newTestData.sysConfig
|
|
|
|
|
|
|
|
|
|
let context: ProcessorContext<any, Function, any> = {
|
|
|
|
|
input: input,
|
|
|
|
|
params: params,
|
|
|
|
|
output: optimizeLayoutProcessorCallBack
|
|
|
|
|
};
|
|
|
|
|
const optimizeLayoutProcessor = new OptimizeLayoutProcessor()
|
|
|
|
|
let res = optimizeLayoutProcessor.exec(context)
|
|
|
|
|
|
|
|
|
|
_handleServe.value = optimizeLayoutProcessor
|
|
|
|
|
//#endregion
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** 优化的处理器回调--这部分 不做到处理器 */
|
|
|
|
|
async function optimizeLayoutProcessorCallBack(context) {
|
|
|
|
|
console.log('optimizeLayoutProcessorCallBack', context);
|
|
|
|
|
const { data, info } = context;
|
|
|
|
|
|
|
|
|
|
if (['noBan', 'stop'].includes(info.type)) {
|
|
|
|
|
await _handleServe.value?.terminateWorker({ goodsId: context.data.pm.goodsId });
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 优化算法拿到优化数据后 各部门根据情况 将数据加载到各自的数据结构中
|
|
|
|
|
let materialPlaceResult = await getMaterialPlaceResult(data);
|
|
|
|
|
if (materialPlaceResult) {
|
|
|
|
|
const { placeResult, pm } = materialPlaceResult;
|
|
|
|
|
const remain = placeResult.boards.filter(e => e.isRemainBoard == true);
|
|
|
|
|
|
|
|
|
|
for (const i in dataBase.value.materialList) {
|
|
|
|
|
let material = dataBase.value.materialList[i];
|
|
|
|
|
|
|
|
|
|
if (material.goodsId == pm.goodsId) {
|
|
|
|
|
// let hasResPm = _handleServe.value?.handlePlaceResult(placeResult, pm);
|
|
|
|
|
let _hasResPm = await handleTempPlaceResultToPlaceMaterial(placeResult, pm);
|
|
|
|
|
|
|
|
|
|
dataBase.value.materialList[i] = {
|
|
|
|
|
...material,
|
|
|
|
|
...pm,
|
|
|
|
|
..._hasResPm,
|
|
|
|
|
optimizingAvgUsageRateExcludeLastBoard: placeResult.avgUsageRateExcludeLastBoard.toFixed(3),
|
|
|
|
|
optimizingUsageRateLastBoard: placeResult.usageRateLastBoard.toFixed(3),
|
|
|
|
|
optimizingBoardCount: placeResult.boardCount,
|
|
|
|
|
optimizingRemainBoardCount: remain.length,
|
|
|
|
|
selectedBlockCount: pm.blockList.length,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setTableData(dataBase.value.materialList);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 数据处理 将优化数据转 为 MaterialPlaceResult */
|
|
|
|
|
function getMaterialPlaceResult(data) {
|
|
|
|
|
let {
|
|
|
|
|
bList, best, yl, pm, width, length
|
|
|
|
|
} = data
|
|
|
|
|
const config = dataBase.value.sysConfig
|
|
|
|
|
|
|
|
|
|
let blocks = bList
|
|
|
|
|
let retData = new MaterialPlaceResult()
|
|
|
|
|
let boardCount = 0
|
|
|
|
|
let remainCount = 0
|
|
|
|
|
let border = config.cutBoardBorder
|
|
|
|
|
let borderOff = (pm.diameter + pm.cutKnifeGap) / 2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 所有大板上的小板面积
|
|
|
|
|
let size_all = 0
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < best.length; i++) {
|
|
|
|
|
let bd = best[i]
|
|
|
|
|
let isRemainBoard = false
|
|
|
|
|
boardCount = retData.boards.length + 1
|
|
|
|
|
if (i < yl.length) // 余料板
|
|
|
|
|
{
|
|
|
|
|
width = yl[i].w + border * 2 - borderOff * 2
|
|
|
|
|
length = yl[i].l + border * 2 - borderOff * 2
|
|
|
|
|
isRemainBoard = true
|
|
|
|
|
remainCount++
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let boardResult = new BoardPlaceResult()
|
|
|
|
|
boardResult.boardId = boardCount
|
|
|
|
|
boardResult.width = width
|
|
|
|
|
boardResult.length = length
|
|
|
|
|
boardResult.isRemainBoard = isRemainBoard
|
|
|
|
|
|
|
|
|
|
let pid = 0
|
|
|
|
|
for (let b of bd) {
|
|
|
|
|
pid++
|
|
|
|
|
let block = blocks[b.bangid]
|
|
|
|
|
let placeStyle = PlaceStyle.FRONT
|
|
|
|
|
if (!block) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
let faceF = block.isTurnFaceToPlace || false
|
|
|
|
|
let isTurnFaceToPlace = config.placeOriginByBoardLocation && (
|
|
|
|
|
config.boardLocation == BoardPosition.RIGHT_BOTTOM || config.boardLocation == BoardPosition.LEFT_TOP)
|
|
|
|
|
if (isTurnFaceToPlace)
|
|
|
|
|
faceF = !faceF
|
|
|
|
|
if (faceF) // 翻面开料
|
|
|
|
|
{
|
|
|
|
|
if (block.texture == 0) {
|
|
|
|
|
placeStyle = PlaceStyle.BACK
|
|
|
|
|
}
|
|
|
|
|
else if (block.texture == 2) {
|
|
|
|
|
placeStyle = PlaceStyle.BACK_TURN_LEFT
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
placeStyle = (b.pbg == block.placeFullLength ? PlaceStyle.BACK : PlaceStyle.BACK_TURN_LEFT)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (block.texture == 0) {
|
|
|
|
|
placeStyle = PlaceStyle.FRONT
|
|
|
|
|
}
|
|
|
|
|
else if (block.texture == 2) {
|
|
|
|
|
placeStyle = PlaceStyle.FRONT_TURN_RIGHT
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
placeStyle = (b.pbg == block.placeFullLength ? PlaceStyle.FRONT : PlaceStyle.FRONT_TURN_RIGHT)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let br: any = null
|
|
|
|
|
br = new BlockPlaceResult(block.blockNo, boardCount, pid, b.x, b.y, b.pbk, b.pbg, placeStyle, block.area)
|
|
|
|
|
boardResult.blocks.push(br)
|
|
|
|
|
boardResult.area += block.area
|
|
|
|
|
}
|
|
|
|
|
retData.boards.push(boardResult)
|
|
|
|
|
size_all += boardResult.area
|
|
|
|
|
|
|
|
|
|
let val = (size_all - boardResult.area) / (retData.boards.length - 1)
|
|
|
|
|
retData.avgUsageRateAll = size_all / retData.boards.length
|
|
|
|
|
retData.avgUsageRateExcludeLastBoard = Number.isNaN(val) ? boardResult.area : val
|
|
|
|
|
retData.usageRateLastBoard = boardResult.area
|
|
|
|
|
retData.boardCount = retData.boards.length
|
|
|
|
|
}
|
|
|
|
|
retData.boardCount = retData.boards.length // 大板数
|
|
|
|
|
let remainBoardCount = retData.boards.filter(t => t.remainNo != '').length // 异形大板数
|
|
|
|
|
let remianCount = 0
|
|
|
|
|
|
|
|
|
|
if (Array.isArray(pm.remainBoardList)) {
|
|
|
|
|
pm.remainBoardList.forEach(e => {
|
|
|
|
|
if (e?.placeBoardJSON) {
|
|
|
|
|
let str = e?.placeBoardJSON
|
|
|
|
|
e.placeBoardList = JSON.parse(str)
|
|
|
|
|
remianCount += e.placeBoardList.length
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
retData.remainBoardCount = pm?.remainBoardList ? remianCount : yl.length + remainBoardCount
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return { placeResult: retData, pm }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function handleTempPlaceResultToPlaceMaterial(_placeResult: MaterialPlaceResult, _pm: PlaceMaterial) {
|
|
|
|
|
console.log('确认优化生效 affirmPlace')
|
|
|
|
|
let pm: PlaceMaterial = _pm
|
|
|
|
|
pm.tempBestPlaceResult = _placeResult
|
|
|
|
|
const config = dataBase.value.sysConfig
|
|
|
|
|
// 没发现优化结果
|
|
|
|
|
if (!pm.tempBestPlaceResult)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
let placeResult = pm.tempBestPlaceResult
|
|
|
|
|
|
|
|
|
|
let orgBoardList = pm.boardList
|
|
|
|
|
|
|
|
|
|
let dic: any = [] // 存放当前 优化的小板
|
|
|
|
|
|
|
|
|
|
pm.boardList = []
|
|
|
|
|
let boardId1 = 1
|
|
|
|
|
// 第一次 false
|
|
|
|
|
if (pm.tempPlaceResultOnyUnlockedBoard) {
|
|
|
|
|
for (let pb of orgBoardList) {
|
|
|
|
|
if (pb.isLocked == false && pb.cutedType == 0) // 未锁定
|
|
|
|
|
{
|
|
|
|
|
pb.blockList.forEach(i => dic[i.blockNo] = i)
|
|
|
|
|
}
|
|
|
|
|
else // 锁定
|
|
|
|
|
{
|
|
|
|
|
if (pb.isAdnormal()) {
|
|
|
|
|
let sb = pm.remainBoardList.find(t => t.id == Number(pb.boardNo))
|
|
|
|
|
if (sb)
|
|
|
|
|
sb.isUsed = true
|
|
|
|
|
}
|
|
|
|
|
pb.boardId = boardId1
|
|
|
|
|
pm.boardList.push(pb)
|
|
|
|
|
boardId1++
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
pm.blockList.forEach(i => dic[i.blockNo] = i)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 0904 修复 需求改造后 导致 这里的dic 最终为空
|
|
|
|
|
if (Object.keys(dic).length == 0) {
|
|
|
|
|
pm.blockList.forEach(i => dic[i.blockNo] = i)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let locator = config.boardLocation
|
|
|
|
|
// 大板优化结果
|
|
|
|
|
let boardId = 0
|
|
|
|
|
for (let bpr of placeResult.boards) {
|
|
|
|
|
boardId++
|
|
|
|
|
// bpr.isRemainBoard false
|
|
|
|
|
let bW = bpr.isRemainBoard ? bpr.width : pm.width
|
|
|
|
|
let bL = bpr.isRemainBoard ? bpr.length : pm.length
|
|
|
|
|
let pb = new PlaceBoard(boardId, bW, bL, bpr.remainId, bpr.remainNo)
|
|
|
|
|
pb.isCreateRemainSpace = true
|
|
|
|
|
|
|
|
|
|
for (let bInfo of bpr.blocks) {
|
|
|
|
|
let block: PlaceBlock = dic[bInfo.blockId]
|
|
|
|
|
|
|
|
|
|
if (block) {
|
|
|
|
|
block.isPlaced = true
|
|
|
|
|
block.boardId = boardId
|
|
|
|
|
block.placeId = bInfo.placeId
|
|
|
|
|
block.placeX = bInfo.placeX
|
|
|
|
|
block.placeY = bInfo.placeY
|
|
|
|
|
// console.log('重置 开料面 开料信息 after', block.boardId, block.blockNo, block, block.placeStyle, bInfo.placeStyle)
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 雕刻机(钻孔、拉槽、开料)优化排版,开料排版面(开料正面)选择顺序:排版面>>造型>>排钻>>设计正面
|
|
|
|
|
1. 排版面
|
|
|
|
|
小板设计排版面为正面或反面,设置对应面为开料排版面,
|
|
|
|
|
小板设计排版面为随意面,则继续;
|
|
|
|
|
2. 造型
|
|
|
|
|
小板只有单面造型,设置对应面为开料排版面,
|
|
|
|
|
小板双面无造型或双面有造型,则继续;
|
|
|
|
|
3. 排钻
|
|
|
|
|
小板有大孔(偏心轮锁孔),设置对应面为开料排版面,
|
|
|
|
|
小板无大孔(偏心轮锁孔),则设置孔多的面为开料排版面,
|
|
|
|
|
小板无孔,则继续;
|
|
|
|
|
4. 设计正面
|
|
|
|
|
默认设置设计正面为开料排版面。
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
block.placeStyle = bInfo.placeStyle
|
|
|
|
|
|
|
|
|
|
let posOff = BlockSizePlus.getOffDis(block)// this.getOffDis(block)
|
|
|
|
|
|
|
|
|
|
block.placeOffX = posOff.x
|
|
|
|
|
block.placeOffY = posOff.y
|
|
|
|
|
block.placeX = bInfo.placeX + posOff.x
|
|
|
|
|
block.placeY = bInfo.placeY + posOff.y
|
|
|
|
|
|
|
|
|
|
if (bInfo.placeStyle == PlaceStyle.FRONT || bInfo.placeStyle == PlaceStyle.FRONT_TURN_BACK
|
|
|
|
|
|| bInfo.placeStyle == PlaceStyle.BACK || bInfo.placeStyle == PlaceStyle.BACK_TURN_BACK) {
|
|
|
|
|
block.placeWidth = block.cutWidth
|
|
|
|
|
block.placeLength = block.cutLength
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
block.placeWidth = block.cutLength
|
|
|
|
|
block.placeLength = block.cutWidth
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
block.isAutoPlaced = true
|
|
|
|
|
block.isOverlap = false
|
|
|
|
|
block.cutOrder = 0
|
|
|
|
|
pb.blockList.push(block)
|
|
|
|
|
pb.blockCount++
|
|
|
|
|
pb.blockArea += block.area
|
|
|
|
|
delete dic[bInfo.blockId] // 移除block;
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (bpr.isScrap) {
|
|
|
|
|
// 设置前余料板的使用状态,将不需要的释放.
|
|
|
|
|
console.log('设置前余料板的使用状态,将不需要的释放.')
|
|
|
|
|
let sb = pm.remainBoardList.find(t => t.id == bpr.remainId)
|
|
|
|
|
if (sb) {
|
|
|
|
|
sb.isUsed = true
|
|
|
|
|
|
|
|
|
|
if (sb.placeStyle % 2 != 0) {
|
|
|
|
|
pb.width = sb.length
|
|
|
|
|
pb.length = sb.width
|
|
|
|
|
}
|
|
|
|
|
let pl = sb.placePolyline
|
|
|
|
|
pb.points = sb?.placePolyline?.LineData.map((t) => { return { x: t.pt.x, y: t.pt.y, bul: t.bul } }) || []
|
|
|
|
|
// pb.StoreNo = sb.StoreHouse;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pb.usageRate = Math.round(10000 * pb.blockArea / pb.area) / 100
|
|
|
|
|
pm.boardList.push(pb)
|
|
|
|
|
console.log('大板靠板翻转', pb.boardId, locator)
|
|
|
|
|
|
|
|
|
|
// 大板靠板翻转
|
|
|
|
|
|
|
|
|
|
PlacePositionHelper.turnPlacePosition(pb, locator, config)
|
|
|
|
|
for (let block of pb.blockList) {
|
|
|
|
|
// 重置 开料面 开料信息
|
|
|
|
|
// console.log('重置 开料面 开料信息', block.boardId, block.blockNo, block, block.placeStyle)
|
|
|
|
|
if (block.placeStyle == null || block.placeStyle == undefined) {
|
|
|
|
|
console.log('handleTempPlaceResultToPlaceMaterial error !block.placeStyle is null or undefined')
|
|
|
|
|
} else {
|
|
|
|
|
PlacePositionClass.resetPlaceStyle(block, block.placeStyle)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 大板长边两侧 width 范围内 避免出现造型 DisPoseModelInBoardBorderWidth > 0 生效
|
|
|
|
|
|
|
|
|
|
DisPoseModelInBoardBorder(
|
|
|
|
|
pm,
|
|
|
|
|
config.boardBorderModelRange,
|
|
|
|
|
config.boardBorderModelModeToFace,
|
|
|
|
|
config.boardBorderModelByMachine,
|
|
|
|
|
config.modelNearBoardBorder,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// for (let pb of pm.boardList) {
|
|
|
|
|
// // 重设大板汇总 重设 大板开料 顺序,下刀点
|
|
|
|
|
// this.resetPlaceBoard(pm, pb)
|
|
|
|
|
// // 检查干涉
|
|
|
|
|
// if (pb.isLocked == false && pb.cutedType == 0)
|
|
|
|
|
// this.checkOverlapInBoard(pm, pb)
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
let rBoardCount = placeResult.boardCount
|
|
|
|
|
let rUseSize_avg = placeResult.avgUsageRateAll
|
|
|
|
|
let rUseSize_noLast = placeResult.avgUsageRateExcludeLastBoard
|
|
|
|
|
let rUseSize_last = placeResult.usageRateLastBoard
|
|
|
|
|
|
|
|
|
|
pm.avgUsageRateAll = rUseSize_avg
|
|
|
|
|
pm.avgUsageRateExcludeLastBoard = rUseSize_noLast
|
|
|
|
|
pm.usageRateLastBoard = rUseSize_last
|
|
|
|
|
pm.boardCount = pm.boardList.length
|
|
|
|
|
pm.remainBoardCount = placeResult.remainBoardCount
|
|
|
|
|
pm.minBoardId = 1
|
|
|
|
|
pm.maxBoardId = pm.boardCount
|
|
|
|
|
|
|
|
|
|
pm.edgeSealLengthList = getMaterialSealEdge(pm)
|
|
|
|
|
|
|
|
|
|
pm.boardCountFlipFace = ArrayExt.count(pm.boardList, t => t.isTwoFaceProcessing())
|
|
|
|
|
|
|
|
|
|
pm.isOptimized = true
|
|
|
|
|
pm.tempBestPlaceResult = null
|
|
|
|
|
pm.tempPlaceResultError = ''
|
|
|
|
|
|
|
|
|
|
let mesg = ''
|
|
|
|
|
let c = 0
|
|
|
|
|
for (let v in dic) {
|
|
|
|
|
mesg += `${v} `
|
|
|
|
|
c++
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mesg = `有${c}片小板未能排入大板,有可能是尖角导致优化失败.${mesg}`
|
|
|
|
|
|
|
|
|
|
if (c > 0) {
|
|
|
|
|
console.log(pm)
|
|
|
|
|
// createMessage.error(mesg)
|
|
|
|
|
|
|
|
|
|
throw new Error(mesg)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return pm
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 绘制下刀点
|
|
|
|
|
*/
|
|
|
|
|
function drawCutPoint() {
|
|
|
|
|
if (!boardEditor.value || !dataBase.value || !_handleServe.value) return;
|
|
|
|
|
|
|
|
|
|
let mIndex = dataBase.value.materialList.findIndex(e => e.goodsId == selectVal.value);
|
|
|
|
|
let pIndex = paginationCurrent.value - 1;
|
|
|
|
|
|
|
|
|
|
if (mIndex >= 0 && dataBase.value.materialList[mIndex].boardList?.length > 0) {
|
|
|
|
|
const pm = dataBase.value.materialList[mIndex];
|
|
|
|
|
const pb = pm.boardList[pIndex];
|
|
|
|
|
|
|
|
|
|
// 计算开料顺序和下刀点
|
|
|
|
|
// _handleServe.value.autoCalcCutOrder(pm, pb);
|
|
|
|
|
CutPointHelper.autoFindCutPoint(pm, pb)
|
|
|
|
|
// 设置显示标志位,只显示小板和下刀点
|
|
|
|
|
displayFlags.value.showBlocks = true;
|
|
|
|
|
displayFlags.value.showCutPoints = !displayFlags.value.showCutPoints; // 切换下刀点显示状态
|
|
|
|
|
|
|
|
|
|
// 重新绘制
|
|
|
|
|
// reDrawCanvas();
|
|
|
|
|
} else {
|
|
|
|
|
alert('请先进行优化!');
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-07-23 10:12:11 +08:00
|
|
|
|
|
2025-07-22 18:22:31 +08:00
|
|
|
|
/**
|
|
|
|
|
* 绘制开料顺序
|
|
|
|
|
*/
|
|
|
|
|
function drawSortingPlace() {
|
|
|
|
|
if (!boardEditor.value || !dataBase.value || !_handleServe.value) return;
|
|
|
|
|
|
|
|
|
|
let mIndex = dataBase.value.materialList.findIndex(e => e.goodsId == selectVal.value);
|
|
|
|
|
let pIndex = paginationCurrent.value - 1;
|
|
|
|
|
|
|
|
|
|
if (mIndex >= 0 && dataBase.value.materialList[mIndex].boardList?.length > 0) {
|
|
|
|
|
const pm = dataBase.value.materialList[mIndex];
|
|
|
|
|
const pb = pm.boardList[pIndex];
|
|
|
|
|
const config = dataBase.value.sysConfig
|
|
|
|
|
// 计算所有板材的 开料顺序
|
|
|
|
|
let newList = CutOrder.autoSetCutOrder(dataBase.value.materialList, config)
|
|
|
|
|
// 计算当前板材的开料顺序
|
|
|
|
|
// CutOrder.autoCalcCutOrder(pm,pb,false,config)
|
|
|
|
|
// 设置显示标志位,只显示小板和开料顺序
|
|
|
|
|
displayFlags.value.showBlocks = true;
|
|
|
|
|
displayFlags.value.showCutOrders = !displayFlags.value.showCutOrders; // 切换开料顺序显示状态
|
|
|
|
|
|
|
|
|
|
// 重新绘制
|
|
|
|
|
// reDrawCanvas();
|
|
|
|
|
} else {
|
|
|
|
|
alert('请先进行优化!');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-23 10:12:11 +08:00
|
|
|
|
|
2025-07-22 18:22:31 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 处理画布事件
|
|
|
|
|
*/
|
|
|
|
|
function boardViewEvent(name, e) {
|
|
|
|
|
if (!boardEditor.value) return;
|
|
|
|
|
|
|
|
|
|
if (name === 'CanvasEvent_MouseDown') {
|
|
|
|
|
// 处理鼠标按下事件
|
|
|
|
|
boardEditor.value.CanvasEvent_MouseDown(e);
|
|
|
|
|
} else if (name === 'CanvasEvent_MouseMove') {
|
|
|
|
|
// 使用节流函数处理鼠标移动事件,减少事件触发频率
|
|
|
|
|
throttledMouseMove(e);
|
|
|
|
|
} else if (name === 'CanvasEvent_Mouseup') {
|
|
|
|
|
boardEditor.value.CanvasEvent_Mouseup(e);
|
|
|
|
|
} else if (name === 'CanvasEvent_dblclick') {
|
|
|
|
|
// 双击事件处理
|
|
|
|
|
} else if (name === 'CanvasEvent_Wheel') {
|
|
|
|
|
// 滚轮事件处理
|
|
|
|
|
} else if (name === 'keyDown') {
|
|
|
|
|
boardEditor.value.keyDown(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const throttledMouseMove = throttle((e) => {
|
|
|
|
|
if (boardEditor.value) {
|
|
|
|
|
boardEditor.value.CanvasEvent_MouseMove(e);
|
|
|
|
|
}
|
|
|
|
|
}, 16);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 节流函数
|
|
|
|
|
*/
|
|
|
|
|
function throttle(fn, delay) {
|
|
|
|
|
let lastCall = 0;
|
|
|
|
|
return function (...args) {
|
|
|
|
|
const now = Date.now();
|
|
|
|
|
if (now - lastCall >= delay) {
|
|
|
|
|
lastCall = now;
|
|
|
|
|
fn.apply(this, args);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 开始排版
|
|
|
|
|
*/
|
|
|
|
|
function startPlace() {
|
|
|
|
|
// initHandleServe();
|
|
|
|
|
initHandleServe1();
|
|
|
|
|
|
|
|
|
|
// 设置显示标志位,显示所有内容
|
|
|
|
|
displayFlags.value.showBlocks = true;
|
|
|
|
|
displayFlags.value.showCutPoints = true;
|
|
|
|
|
displayFlags.value.showCutOrders = true;
|
|
|
|
|
displayFlags.value.showCutArrow = true;
|
|
|
|
|
displayFlags.value.showCutNo = true;
|
|
|
|
|
displayFlags.value.showHoles = true;
|
|
|
|
|
displayFlags.value.showModels = true;
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-23 10:12:11 +08:00
|
|
|
|
|
2025-07-22 18:22:31 +08:00
|
|
|
|
/**
|
|
|
|
|
* 清空画布
|
|
|
|
|
*/
|
|
|
|
|
function clearCanvas() {
|
|
|
|
|
// 重置显示标志位
|
|
|
|
|
displayFlags.value.showBlocks = false;
|
|
|
|
|
displayFlags.value.showCutPoints = false;
|
|
|
|
|
displayFlags.value.showCutOrders = false;
|
|
|
|
|
displayFlags.value.showCutArrow = false;
|
|
|
|
|
displayFlags.value.showCutNo = false;
|
|
|
|
|
displayFlags.value.showHoles = false;
|
|
|
|
|
displayFlags.value.showModels = false;
|
|
|
|
|
// 清空画布
|
|
|
|
|
boardEditor.value?.clearCanvas();
|
|
|
|
|
}
|
2025-07-23 10:12:11 +08:00
|
|
|
|
|
2025-07-22 18:22:31 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取解析器参数
|
|
|
|
|
*/
|
|
|
|
|
function getParserParams() {
|
|
|
|
|
handleTemplateData();
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-23 10:12:11 +08:00
|
|
|
|
|
2025-07-22 18:22:31 +08:00
|
|
|
|
/**
|
|
|
|
|
* 处理模板数据
|
|
|
|
|
*/
|
|
|
|
|
async function handleTemplateData() {
|
|
|
|
|
// 获取模板和范例
|
|
|
|
|
let templateData = parserMain.value._device.getTemplateData();
|
|
|
|
|
console.log(templateData, dataBase.value);
|
|
|
|
|
|
|
|
|
|
if (!currentMaterial.value || !currentBoard.value) {
|
|
|
|
|
alert('请先进行优化!');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 准备代码参数列表
|
|
|
|
|
let data: CodeParamsList = {
|
|
|
|
|
processList: [],
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 获取速度参数
|
|
|
|
|
let freeSpeed = _handleServe.value?.freeSpeed || 10000;
|
|
|
|
|
let workSpeed = _handleServe.value?.workSpeed || 8000;
|
|
|
|
|
let modelSpeed = _handleServe.value?.modelSpeed || 8000;
|
|
|
|
|
let holeSpeed = _handleServe.value?.holeSpeed || 8000;
|
2025-07-23 10:12:11 +08:00
|
|
|
|
|
|
|
|
|
/** 根据哪个加工面加工 */
|
|
|
|
|
let doBackFace = true
|
2025-07-22 18:22:31 +08:00
|
|
|
|
for (const template of templateData) {
|
|
|
|
|
// 必须要有指令和代码
|
|
|
|
|
if (!template.value || !template.orderStr) continue;
|
|
|
|
|
|
|
|
|
|
if (template.isLoop) {
|
|
|
|
|
// 处理循环节点(加工刀路数据)
|
|
|
|
|
let material = currentMaterial.value;
|
|
|
|
|
let board = currentBoard.value;
|
|
|
|
|
// 根据开料顺序做个排序
|
|
|
|
|
board.blockList = board.blockList.sort((a, b) => a.cutOrder - b.cutOrder)
|
|
|
|
|
|
|
|
|
|
//#region 排钻
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 先对该大板内所有小板上的孔进行分析
|
|
|
|
|
*/
|
|
|
|
|
|
2025-07-23 10:12:11 +08:00
|
|
|
|
let allHoles: BlockHole[] = await BlockHelper.GetHoles_BoardAllBlocksByDoFace(board,doBackFace)
|
2025-07-22 18:22:31 +08:00
|
|
|
|
// 对孔列表 根据 孔直径 排序
|
|
|
|
|
allHoles = allHoles.sort((a, b) => a.radius - b.radius)
|
|
|
|
|
|
|
|
|
|
for (const key in allHoles) {
|
|
|
|
|
let hole = allHoles[key]
|
|
|
|
|
let block: PlaceBlock = board.blockList.find(e => e.blockNo == hole.blockNo)
|
|
|
|
|
|
|
|
|
|
// 加工项 孔的
|
|
|
|
|
let temp: CodeParamsObj = {
|
|
|
|
|
processItemInfo: {
|
|
|
|
|
code: template.value,
|
|
|
|
|
order: template.orderStr,
|
|
|
|
|
block: {
|
|
|
|
|
blockNo: block.blockNo,
|
|
|
|
|
cutLength: block.cutLength,
|
|
|
|
|
cutWidth: block.cutWidth
|
|
|
|
|
},
|
|
|
|
|
knife: {
|
|
|
|
|
diameter: hole.radius * 2
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
let list: CodeParams[] = [];
|
|
|
|
|
let depth = hole.depth >= block.thickness ? block.thickness : hole.depth
|
|
|
|
|
// 刀移动到孔的安全点
|
|
|
|
|
let moveToHolePoint = pointToCodeParams(hole.pointX, hole.pointY, block.placeX, block.placeY)
|
|
|
|
|
moveToHolePoint.dir = 0
|
|
|
|
|
moveToHolePoint.z = 30
|
|
|
|
|
moveToHolePoint.f = freeSpeed
|
|
|
|
|
list.push(moveToHolePoint)
|
|
|
|
|
// 刀下到版面
|
|
|
|
|
let moveToblockToDoHole = pointToCodeParams(hole.pointX, hole.pointY, block.placeX, block.placeY)
|
|
|
|
|
moveToblockToDoHole.dir = 0
|
|
|
|
|
moveToblockToDoHole.z = -block.thickness
|
|
|
|
|
moveToblockToDoHole.f = freeSpeed
|
|
|
|
|
list.push(moveToblockToDoHole)
|
|
|
|
|
// 下刀
|
|
|
|
|
let knifeDown_DoHole = pointToCodeParams(hole.pointX, hole.pointY, block.placeX, block.placeY)
|
|
|
|
|
knifeDown_DoHole.z = -depth
|
|
|
|
|
knifeDown_DoHole.dir = 1
|
|
|
|
|
knifeDown_DoHole.f = holeSpeed
|
|
|
|
|
list.push(knifeDown_DoHole)
|
|
|
|
|
// 抬刀
|
|
|
|
|
let knifeEnd_DoHoleEnd = pointToCodeParams(hole.pointX, hole.pointY, block.placeX, block.placeY)
|
|
|
|
|
knifeEnd_DoHoleEnd.dir = 0
|
|
|
|
|
knifeEnd_DoHoleEnd.z = 30
|
|
|
|
|
knifeEnd_DoHoleEnd.f = freeSpeed
|
|
|
|
|
list.push(knifeEnd_DoHoleEnd)
|
|
|
|
|
|
|
|
|
|
temp.list = list
|
|
|
|
|
|
|
|
|
|
data.processList?.push(temp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//#endregion
|
|
|
|
|
|
|
|
|
|
//#region 造型
|
|
|
|
|
|
|
|
|
|
// 所有造型
|
2025-07-23 10:12:11 +08:00
|
|
|
|
let allModels: BlockModel[] = await BlockHelper.GetModels_BoardAllBlocksByDoFace(board,doBackFace)
|
2025-07-22 18:22:31 +08:00
|
|
|
|
allModels = allModels.sort((a, b) => a.knifeRadius - b.knifeRadius)
|
|
|
|
|
|
|
|
|
|
for (const key in allModels) {
|
|
|
|
|
let model = allModels[key]
|
|
|
|
|
let block: PlaceBlock = board.blockList.find(e => e.blockNo == model.blockNo)
|
|
|
|
|
let { placeX, placeY } = block;
|
|
|
|
|
|
|
|
|
|
let temp: CodeParamsObj = {
|
|
|
|
|
processItemInfo: {
|
|
|
|
|
code: template.value,
|
|
|
|
|
order: template.orderStr,
|
|
|
|
|
block: {
|
|
|
|
|
blockNo: block.blockNo,
|
|
|
|
|
cutLength: block.cutLength,
|
|
|
|
|
cutWidth: block.cutWidth
|
|
|
|
|
},
|
|
|
|
|
knife: {
|
|
|
|
|
diameter: model.realKnifeRadius * 2
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
let list: CodeParams[] = [];
|
|
|
|
|
let realPointList:any[] = []
|
|
|
|
|
// model.realPointList.forEach((p,i)=>{
|
|
|
|
|
// if(p.curve !=0 || p.radius != 0){
|
|
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
// })
|
|
|
|
|
for (let index = 0; index < model.realPointList.length; index++) {
|
|
|
|
|
const p = model.realPointList[index];
|
|
|
|
|
let last_p: BlockModelPoint;
|
|
|
|
|
if (index == 0) {
|
|
|
|
|
last_p = model.realPointList[model.realPointList.length - 1]
|
|
|
|
|
} else {
|
|
|
|
|
last_p = model.realPointList[index - 1]
|
|
|
|
|
}
|
|
|
|
|
// p.curve
|
|
|
|
|
// p.radius
|
|
|
|
|
let new_p = { ...p, radius: last_p.radius, curve: last_p.curve }
|
|
|
|
|
realPointList.push(new_p);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let depth = model.depth >= block.thickness ? block.thickness : model.depth
|
|
|
|
|
|
|
|
|
|
// 移动到起点
|
|
|
|
|
let codeLineStart = pointToCodeParams(realPointList[0].pointX, realPointList[0].pointY, placeX, placeY)
|
|
|
|
|
codeLineStart.dir = 0;
|
|
|
|
|
codeLineStart.z = 30;
|
|
|
|
|
codeLineStart.f = freeSpeed;
|
|
|
|
|
list.push(codeLineStart);
|
|
|
|
|
// 下刀至版面
|
|
|
|
|
let knifeToBlock_DoModel = pointToCodeParams(realPointList[0].pointX, realPointList[0].pointY, placeX, placeY)
|
|
|
|
|
knifeToBlock_DoModel.dir = 0;
|
|
|
|
|
knifeToBlock_DoModel.z = block.thickness;
|
|
|
|
|
knifeToBlock_DoModel.f = freeSpeed
|
|
|
|
|
list.push(knifeToBlock_DoModel)
|
|
|
|
|
// 扎入 下刀至起点
|
|
|
|
|
let knifeInnerBlock_DoBlock = pointToCodeParams(realPointList[0].pointX, realPointList[0].pointY, placeX, placeY)
|
|
|
|
|
knifeInnerBlock_DoBlock.dir = 1;
|
|
|
|
|
knifeInnerBlock_DoBlock.z = -depth
|
|
|
|
|
knifeInnerBlock_DoBlock.f = modelSpeed
|
|
|
|
|
list.push(knifeInnerBlock_DoBlock)
|
|
|
|
|
// 开始造型走刀
|
|
|
|
|
for (const modelPoint of realPointList) {
|
|
|
|
|
let codeLineMove = pointToCodeParams(modelPoint.pointX, modelPoint.pointY, placeX, placeY, modelPoint.curve)
|
|
|
|
|
codeLineMove.z = -depth
|
|
|
|
|
codeLineMove.f = modelSpeed
|
|
|
|
|
if (modelPoint.radius != 0) {
|
|
|
|
|
codeLineMove.r = modelPoint.radius
|
|
|
|
|
}
|
|
|
|
|
list.push(codeLineMove)
|
|
|
|
|
}
|
|
|
|
|
// 走刀结束 抬刀
|
|
|
|
|
let endPoint = realPointList[realPointList.length - 1]
|
|
|
|
|
let codeLineEnd = pointToCodeParams(endPoint.pointX, endPoint.pointY, placeX, placeY)
|
|
|
|
|
codeLineEnd.dir = 0
|
|
|
|
|
codeLineEnd.f = freeSpeed
|
|
|
|
|
codeLineEnd.z = 30
|
|
|
|
|
list.push(codeLineEnd)
|
|
|
|
|
temp.list = list
|
|
|
|
|
data.processList?.push(temp);
|
|
|
|
|
}
|
|
|
|
|
//#endregion
|
|
|
|
|
|
|
|
|
|
//#region 开料
|
|
|
|
|
|
|
|
|
|
// 轮廓的集合 开料用
|
|
|
|
|
let borderFinalList = board.blockList.map(e => e.blockDetail.borderContour.borderFinal);
|
|
|
|
|
for (const i in borderFinalList) {
|
|
|
|
|
let block = board.blockList[i];
|
|
|
|
|
let border = borderFinalList[i];
|
|
|
|
|
|
|
|
|
|
// 添加标记
|
|
|
|
|
let temp1: CodeParamsObj = {
|
|
|
|
|
processItemInfo: {
|
|
|
|
|
code: 'MARK',
|
|
|
|
|
order: 'Mark',
|
|
|
|
|
codeParams: block.blockNo + ' cut block'
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
data.processList?.push(temp1);
|
|
|
|
|
|
|
|
|
|
// 加工项 开料的
|
|
|
|
|
let temp: CodeParamsObj = {
|
|
|
|
|
processItemInfo: {
|
|
|
|
|
code: template.value,
|
|
|
|
|
order: template.orderStr,
|
|
|
|
|
block: {
|
|
|
|
|
cutLength: block.cutLength,
|
|
|
|
|
cutWidth: block.cutWidth
|
|
|
|
|
},
|
|
|
|
|
knife: {
|
|
|
|
|
diameter: material.diameter
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 加工刀路信息 代码生成参数列表
|
|
|
|
|
let list: CodeParams[] = [];
|
|
|
|
|
let { placeX, placeY } = block;
|
|
|
|
|
|
|
|
|
|
// 移动到起点
|
|
|
|
|
let codeLineStart = BoardToCodeParams(border[0], placeX, placeY);
|
|
|
|
|
codeLineStart.dir = 0;
|
|
|
|
|
codeLineStart.z = 30;
|
|
|
|
|
codeLineStart.f = freeSpeed;
|
|
|
|
|
list.push(codeLineStart);
|
|
|
|
|
|
|
|
|
|
// 下刀到板面
|
|
|
|
|
let codeLine1 = BoardToCodeParams(border[0], placeX, placeY);
|
|
|
|
|
codeLine1.dir = 0;
|
|
|
|
|
codeLine1.z = block.thickness;
|
|
|
|
|
codeLine1.f = freeSpeed;
|
|
|
|
|
list.push(codeLine1);
|
|
|
|
|
|
|
|
|
|
// 扎入
|
|
|
|
|
let codeLine2 = BoardToCodeParams(border[0], placeX, placeY);
|
|
|
|
|
codeLine2.dir = 1;
|
|
|
|
|
codeLine2.z = 0;
|
|
|
|
|
codeLine2.f = workSpeed;
|
|
|
|
|
|
|
|
|
|
// 走刀
|
|
|
|
|
for (const p of border) {
|
|
|
|
|
// if (block.blockNo == '25044454400') {
|
|
|
|
|
// debugger
|
|
|
|
|
// }
|
|
|
|
|
let codeLine = BoardToCodeParams(p, placeX, placeY);
|
|
|
|
|
codeLine.z = -block.thickness;
|
|
|
|
|
codeLine.f = workSpeed;
|
|
|
|
|
list.push(codeLine);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 回到起点
|
|
|
|
|
let codeLine3 = BoardToCodeParams(border[0], placeX, placeY);
|
|
|
|
|
codeLine3.z = -block.thickness;
|
|
|
|
|
codeLine3.f = freeSpeed;
|
|
|
|
|
list.push(codeLine3);
|
|
|
|
|
|
|
|
|
|
// 抬刀
|
|
|
|
|
let codeLineEnd = BoardToCodeParams(border[0], placeX, placeY);
|
|
|
|
|
codeLineEnd.dir = 0;
|
|
|
|
|
codeLineEnd.z = 30;
|
|
|
|
|
codeLineEnd.f = freeSpeed;
|
|
|
|
|
list.push(codeLineEnd);
|
|
|
|
|
|
|
|
|
|
temp.list = list;
|
|
|
|
|
data.processList?.push(temp);
|
|
|
|
|
}
|
|
|
|
|
//#endregion
|
|
|
|
|
} else {
|
|
|
|
|
// 处理非循环节点(文件头尾)
|
|
|
|
|
let temp: CodeParamsObj = {
|
|
|
|
|
processItemInfo: {
|
|
|
|
|
code: template.value,
|
|
|
|
|
order: template.orderStr
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (template.params) {
|
|
|
|
|
temp.processItemInfo.codeParams = template.params;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data.processList?.push(temp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.log('处理完成', data);
|
|
|
|
|
|
|
|
|
|
// 生成代码
|
|
|
|
|
let str = await parserMain.value.getCode(data);
|
|
|
|
|
testData1.value = str;
|
|
|
|
|
console.log('最终结果', str);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 将板轮廓转换为代码参数
|
|
|
|
|
* border 轮廓线
|
|
|
|
|
* placeX 板件优化X坐标
|
|
|
|
|
* placeY 板件优化Y坐标
|
|
|
|
|
*/
|
|
|
|
|
function BoardToCodeParams(border: Curve2d | Arc2d, placeX = 0, placeY = 0): CodeParams {
|
|
|
|
|
let codeLine: CodeParams = {};
|
|
|
|
|
codeLine.x = border.EndPoint.m_X + placeX;
|
|
|
|
|
codeLine.y = border.EndPoint.m_Y + placeY;
|
|
|
|
|
codeLine.dir = 1;
|
|
|
|
|
|
|
|
|
|
if (border instanceof Arc2d || (Reflect.has(border, 'm_Radius') && border['m_Radius'] != 0)) {
|
|
|
|
|
codeLine.r = border.m_Radius;
|
|
|
|
|
if (border.Bul > 0) {
|
|
|
|
|
codeLine.dir = 3;
|
|
|
|
|
} else if (border.Bul < 0) {
|
|
|
|
|
codeLine.dir = 2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return codeLine;
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* x , y 点坐标
|
|
|
|
|
* hole 孔
|
|
|
|
|
* placeX 板件优化X坐标
|
|
|
|
|
* placeY 板件优化Y坐标
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
function pointToCodeParams(x, y, placeX = 0, placeY = 0, bul?) {
|
|
|
|
|
let codeLine: CodeParams = {}
|
|
|
|
|
codeLine.x = x + placeX
|
|
|
|
|
codeLine.y = y + placeY
|
|
|
|
|
|
|
|
|
|
if (bul != undefined) {
|
|
|
|
|
if (bul > 0) {
|
|
|
|
|
codeLine.dir = 3
|
|
|
|
|
} else if (bul < 0) {
|
|
|
|
|
codeLine.dir = 2
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return codeLine
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* 重新绘制画布
|
|
|
|
|
*/
|
|
|
|
|
function reDrawCanvas() {
|
|
|
|
|
if (!boardEditor.value || !dataBase.value) return;
|
|
|
|
|
|
|
|
|
|
let mIndex = dataBase.value.materialList.findIndex(e => e.goodsId == selectVal.value);
|
|
|
|
|
let pIndex = paginationCurrent.value - 1;
|
|
|
|
|
|
|
|
|
|
if (mIndex >= 0 && dataBase.value.materialList[mIndex].boardList?.length > 0) {
|
|
|
|
|
const pm = dataBase.value.materialList[mIndex];
|
|
|
|
|
const pb = pm.boardList[pIndex];
|
|
|
|
|
|
|
|
|
|
// 确保每个板件都有开料顺序和下刀点
|
|
|
|
|
if (_handleServe.value && pb.blockList.some(block => !block.cutOrder)) {
|
|
|
|
|
_handleServe.value.autoCalcCutOrder(pm, pb);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
boardEditor.value.setMaterial(pm);
|
|
|
|
|
boardEditor.value.setBoard(pb);
|
|
|
|
|
|
|
|
|
|
// 清空画布并绘制基础内容
|
|
|
|
|
boardEditor.value.clearCanvas();
|
|
|
|
|
boardEditor.value.drawBase();
|
|
|
|
|
boardEditor.value.drawBoard(pb);
|
|
|
|
|
|
|
|
|
|
boardEditor.value.setDisplayFlags({
|
|
|
|
|
isLockd: displayFlags.value.isLockd,
|
|
|
|
|
showBlocks: displayFlags.value.showBlocks,
|
|
|
|
|
showCutPoints: displayFlags.value.showCutPoints,
|
|
|
|
|
showCutOrders: displayFlags.value.showCutOrders,
|
|
|
|
|
showCutArrow: displayFlags.value.showCutArrow,
|
|
|
|
|
showCutNo: displayFlags.value.showCutNo,
|
|
|
|
|
showHoles: displayFlags.value.showHoles,
|
|
|
|
|
showModels: displayFlags.value.showModels,
|
|
|
|
|
showManualPlace: displayFlags.value.showManualPlace
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
boardEditor.value.drawAllElements();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
<div class="processDemo1">
|
|
|
|
|
<div class="tools">
|
|
|
|
|
<span class="toolItemLabel">生产单号:</span>
|
|
|
|
|
<Input class="toolItem" v-model:value="orderNo" style="width: 170px;" @change="orderNoChange" />
|
|
|
|
|
|
|
|
|
|
<span class="toolItemLabel">机台选择:</span>
|
|
|
|
|
<Select v-model:value="selectedMachineID" placeholder="请选择机台" :get-popup-container="getPopupContainer"
|
|
|
|
|
style="width: 170px;" @change="machineChange">
|
|
|
|
|
<SelectOption v-for="item in machineList" :key="item.id" :value="item.id">
|
|
|
|
|
{{ item.name }}
|
|
|
|
|
</SelectOption>
|
|
|
|
|
</Select>
|
|
|
|
|
|
|
|
|
|
<Button v-if="!isOptimizeing" @click="startPlace">开始优化</Button>
|
2025-07-23 10:12:11 +08:00
|
|
|
|
|
2025-07-22 18:22:31 +08:00
|
|
|
|
<Button @click="drawSortingPlace">开料顺序</Button>
|
|
|
|
|
<Button @click="drawCutPoint">下刀点</Button>
|
|
|
|
|
<Button @click="getParserParams"> 解析器</Button>
|
|
|
|
|
<BasicTable @register="registerTable" />
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="content">
|
|
|
|
|
<div class="contentLeft">
|
|
|
|
|
<div class="contentTools">
|
|
|
|
|
|
|
|
|
|
<Select v-model:value="selectVal" class="plateSelect" :style="{ width: '200px', marginLeft: '10px' }"
|
|
|
|
|
:options="plateSelectOptions" :field-names="{ label: 'goodsName', value: 'goodsId' }"
|
|
|
|
|
@change="reDrawCanvas" />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<Pagination v-model:current="paginationCurrent" @change="reDrawCanvas" :page-size="1" class="platePagination"
|
|
|
|
|
:total="paginationCurrentAll" />
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="contentBtns">
|
|
|
|
|
<Button class="contentBtn" @click="clearCanvas">清空</Button>
|
2025-07-23 10:12:11 +08:00
|
|
|
|
|
2025-07-22 18:22:31 +08:00
|
|
|
|
|
|
|
|
|
<Textarea class="testData" v-model:value="testData1"></Textarea>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 画布区域 -->
|
|
|
|
|
<div class="contentMain" ref="canvasMain">
|
|
|
|
|
<BoardView ref="canvas" class="BoardView" :width="canvasWidth" :height="canvasHeight" tabindex="0"
|
|
|
|
|
@keydown="boardViewEvent('keyDown', $event)" @dblclick="boardViewEvent('CanvasEvent_dblclick', $event)"
|
|
|
|
|
@mousedown="boardViewEvent('CanvasEvent_MouseDown', $event)"
|
|
|
|
|
@mouseup="boardViewEvent('CanvasEvent_Mouseup', $event)"
|
|
|
|
|
@mousemove="boardViewEvent('CanvasEvent_MouseMove', $event)"
|
|
|
|
|
@wheel="boardViewEvent('CanvasEvent_Wheel', $event)"
|
|
|
|
|
@contextmenu="boardViewEvent('CanvasEvent_RightClick', $event)" />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<style>
|
|
|
|
|
.processDemo1 {
|
|
|
|
|
height: 100%;
|
|
|
|
|
width: 100%;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
padding: 10px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tools {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: row;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.toolItemLabel {
|
|
|
|
|
margin: auto 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.content {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: row;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.contentLeft {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
flex: 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.contentTools {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: row;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.BoardView {
|
|
|
|
|
border: 1px solid silver;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.contentBtns {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: row;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.contentBtn {
|
|
|
|
|
margin: 6px 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.testData {
|
|
|
|
|
overflow: auto;
|
|
|
|
|
min-height: 450px !important;
|
|
|
|
|
background-color: #FFFFFF !important;
|
|
|
|
|
color: #000000 !important;
|
|
|
|
|
}
|
|
|
|
|
</style>
|