import { ArrayExt } from '../../common/base/ArrayExt.js' import type { Arc2d, Curve2d } from '../../common/base/CAD.js' import { CADExt, Line2d } from '../../common/base/CAD.js' import { BlockRegion, FaceType, HoleType, HoleArrange, PlaceStyle, TextureType, BlockBorderPoint, BlockHole, BlockModel, BlockModelPoint, PlacePositionClass, PlaceBlock, PlaceMaterial, PlaceBoard } from '../../confClass.js' import { equal } from '../../common/base/MathComm.js' import { PolylineHelper } from '../../common/LayoutEngine/PolylineHelper.js' import { Point } from '../../common/Vector2.js' import { BlockPlus } from './BlockPlus.js' import { BlockSizePlus } from './BlockSizePlus.js' import { NcAdvanceHelper } from '@/imes/biz/NcAdvance.js' // './NcAdvance.js' import { getPlaceBoard, resetPlaceBoard, resetPlaceMaterial } from './PlaceBase' import { resetModelKnife } from './BlockDataPlus.js' /** 小板业务类 */ export class BlockHelper { // static testBlockNo = ''; //测试板号 /** 初始化小板明细 */ static setBlockDetail(block: PlaceBlock) { if (block.blockDetail) return // 已存在 } // 初始化block ,边框,内部边框,偏移后等---------------------------------------- /** 初始化 block (初始化明细,重设排版) */ private static equal(a, b, off = 0.001): boolean { return Math.abs(a - b) < off } // 排版相关:小板翻转,移动--------------------------------------------------- /** 翻转小板,翻转动作opType: 0翻面 1右转 2后转 3左转 */ static turnBlock(block: PlaceBlock, placeMaterial: PlaceMaterial, opType: number) { let orgStyle = block.placeStyle let newStyle = BlockHelper.getTurnedPlaceStyle(orgStyle, opType) 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.placeOffX = offset.x block.placeOffY = offset.y // 修改小板的放置方式 console.log('修改小板的放置方式', block.blockNo, block, newStyle) // BlockHelper.resetPlaceStyle(block, newStyle) PlacePositionClass.resetPlaceStyle(block, newStyle); this.resetDoFace_HoleModel(block, false) this.restOther(block) // 重置放置,检查冲突 BlockHelper.replaceBlock(placeMaterial, block, block.boardId, new Point(newPlaceX, newPlaceY)) } /** 获得翻转后的新放置方式, 翻转动作opType: 0翻面 1右转 2后转 3左转 */ static getTurnedPlaceStyle(orgStyle: PlaceStyle, opType: number): PlaceStyle { let newStyle: number = orgStyle if (opType == 0) // 翻面 { switch (orgStyle) { case PlaceStyle.FRONT: // 正面 newStyle = PlaceStyle.BACK // 反面 break case PlaceStyle.FRONT_TURN_RIGHT: // 正面右转 newStyle = PlaceStyle.BACK_TURN_LEFT // 反面左转 break case PlaceStyle.FRONT_TURN_BACK: // 正面后转 newStyle = PlaceStyle.BACK_TURN_BACK // 反面后转 break case PlaceStyle.FRONT_TURN_LEFT: // 正面左转 newStyle = PlaceStyle.BACK_TURN_RIGHT // 反面右转 break case PlaceStyle.BACK: // 反面 newStyle = PlaceStyle.FRONT // 正面 break case PlaceStyle.BACK_TURN_RIGHT: // 反面右转 newStyle = PlaceStyle.FRONT_TURN_LEFT // 正面左转 break case PlaceStyle.BACK_TURN_BACK: // 反面后转 newStyle = PlaceStyle.FRONT_TURN_BACK // 正面后转 break case PlaceStyle.BACK_TURN_LEFT: // 反面左转 newStyle = PlaceStyle.FRONT_TURN_RIGHT // 正面右转 break default: break } } else if (opType == 1) // 右转 { newStyle = orgStyle + 1 if (newStyle == 4) newStyle = 0 if (newStyle == 8) newStyle = 4 } else if (opType == 2) // 后转 { newStyle = orgStyle + 2 if (orgStyle < 4 && newStyle >= 4) newStyle = newStyle - 4 if (orgStyle >= 4 && newStyle >= 8) newStyle = newStyle - 4 } else if (opType == 3) // 左转 { newStyle = orgStyle - 1 if (newStyle == 3) newStyle = 7 if (newStyle == -1) newStyle = 3 } return newStyle } /** 板放置后,重置placeWidth, placeLength, 封边, 正反面, 面孔, 造型等 */ static resetPlaceStyle(block: PlaceBlock, newStyle: PlaceStyle) { block.placeStyle = newStyle // tryFix let _width = block.cutWidth let _lenth = block.cutLength if (block.width > block.length) { block.cutWidth = Math.max(_width, _lenth) block.cutLength = Math.min(_width, _lenth) } else { block.cutWidth = Math.min(_width, _lenth) block.cutLength = Math.max(_width, _lenth) } switch (newStyle) { case PlaceStyle.FRONT: // 正面 block.placeWidth = block.cutWidth block.placeLength = block.cutLength block.placeSealLeft = block.sealLeft block.placeSealRight = block.sealRight block.placeSealTop = block.sealTop block.placeSealBottom = block.sealBottom block.holeCountSideLeft = block.holeCountLeft() block.holeCountSideRight = block.holeCountRight() block.holeCountSideTop = block.holeCountTop() block.holeCountSideBottom = block.holeCountBottom() block.placeDirection = '→' block.placeDirection_Length = block.length > block.width - 0.001 ? '→' : '↓' break case PlaceStyle.FRONT_TURN_RIGHT: // 正面右转 block.placeWidth = block.cutLength block.placeLength = block.cutWidth block.placeSealLeft = block.sealBottom block.placeSealRight = block.sealTop block.placeSealTop = block.sealLeft block.placeSealBottom = block.sealRight block.holeCountSideLeft = block.holeCountBottom() block.holeCountSideRight = block.holeCountTop() block.holeCountSideTop = block.holeCountLeft() block.holeCountSideBottom = block.holeCountRight() block.placeDirection = '↓' block.placeDirection_Length = block.length > block.width - 0.001 ? '↓' : '←' break case PlaceStyle.FRONT_TURN_BACK: // 正面后转 block.placeWidth = block.cutWidth block.placeLength = block.cutLength block.placeSealLeft = block.sealRight block.placeSealRight = block.sealLeft block.placeSealTop = block.sealBottom block.placeSealBottom = block.sealTop block.holeCountSideLeft = block.holeCountRight() block.holeCountSideRight = block.holeCountLeft() block.holeCountSideTop = block.holeCountBottom() block.holeCountSideBottom = block.holeCountTop() block.placeDirection = '←' block.placeDirection_Length = block.length > block.width - 0.001 ? '←' : '↑' break case PlaceStyle.FRONT_TURN_LEFT: // 正面左转 block.placeWidth = block.cutLength block.placeLength = block.cutWidth block.placeSealLeft = block.sealTop block.placeSealRight = block.sealBottom block.placeSealTop = block.sealRight block.placeSealBottom = block.sealLeft block.holeCountSideLeft = block.holeCountTop() block.holeCountSideRight = block.holeCountBottom() block.holeCountSideTop = block.holeCountRight() block.holeCountSideBottom = block.holeCountLeft() block.placeDirection = '↑' block.placeDirection_Length = block.length > block.width - 0.001 ? '↑' : '→' break case PlaceStyle.BACK: // 反面 block.placeWidth = block.cutWidth block.placeLength = block.cutLength block.placeSealLeft = block.sealRight block.placeSealRight = block.sealLeft block.placeSealTop = block.sealTop block.placeSealBottom = block.sealBottom block.holeCountSideLeft = block.holeCountRight() block.holeCountSideRight = block.holeCountLeft() block.holeCountSideTop = block.holeCountTop() block.holeCountSideBottom = block.holeCountBottom() block.placeDirection = '→' block.placeDirection_Length = block.length > block.width - 0.001 ? '→' : '↑' break case PlaceStyle.BACK_TURN_RIGHT: // 反面右转 block.placeWidth = block.cutLength block.placeLength = block.cutWidth block.placeSealLeft = block.sealBottom block.placeSealRight = block.sealTop block.placeSealTop = block.sealRight block.placeSealBottom = block.sealLeft block.holeCountSideLeft = block.holeCountBottom() block.holeCountSideRight = block.holeCountTop() block.holeCountSideTop = block.holeCountRight() block.holeCountSideBottom = block.holeCountLeft() block.placeDirection = '↓' block.placeDirection_Length = block.length > block.width - 0.001 ? '↓' : '→' break case PlaceStyle.BACK_TURN_BACK: // 反面后转 block.placeWidth = block.cutWidth block.placeLength = block.cutLength block.placeSealLeft = block.sealLeft block.placeSealRight = block.sealRight block.placeSealTop = block.sealTop block.placeSealBottom = block.sealBottom block.holeCountSideLeft = block.holeCountLeft() block.holeCountSideRight = block.holeCountRight() block.holeCountSideTop = block.holeCountTop() block.holeCountSideBottom = block.holeCountBottom() block.placeDirection = '←' block.placeDirection_Length = block.length > block.width - 0.001 ? '←' : '↓' break case PlaceStyle.BACK_TURN_LEFT: // 反面左转 block.placeWidth = block.cutLength block.placeLength = block.cutWidth block.placeSealLeft = block.sealTop block.placeSealRight = block.sealBottom block.placeSealTop = block.sealLeft block.placeSealBottom = block.sealRight block.holeCountSideLeft = block.holeCountTop() block.holeCountSideRight = block.holeCountBottom() block.holeCountSideTop = block.holeCountLeft() block.holeCountSideBottom = block.holeCountRight() block.placeDirection = '↑' block.placeDirection_Length = block.length > block.width - 0.001 ? '↑' : '←' break default: break } this.resetDoFace_HoleModel(block) this.restOther(block) } /** 获得小板放置方向标识 */ static getPlaceDirection(block: PlaceBlock): string { return block.placeDirection } /** 选择最近的板,弹出定位方向盘,选择定位位置 */ static replaceBlockWidthDirect(pm: PlaceMaterial, block: PlaceBlock, newBoardId: number, dragingBlockPoint: BlockBorderPoint, referBlockPoint: BlockBorderPoint, direction: number) { let gap = pm.diameter + pm.cutKnifeGap // '↖', '↑', '↗', '←', 'X', '→', '↙', '↓', '↘' // 参照点 现在位置 let rPointX = referBlockPoint.placeX let rPointY = referBlockPoint.placeY if (direction == 0) // '↖' { rPointX -= gap rPointY -= gap } if (direction == 1) // '↑' { rPointX -= gap } if (direction == 2) // '↗' { rPointX -= gap rPointY += gap } if (direction == 3) // '←' { rPointY -= gap } if (direction == 4) // '←' { } if (direction == 5) // '→' { rPointY += gap } if (direction == 6) // '↙' { rPointX += gap rPointY -= gap } if (direction == 7) // '↓' { rPointX += gap } if (direction == 8) // '↘' { rPointX += gap rPointY += gap } // 减去拖拉点自身与基点的距离 rPointX = rPointX - dragingBlockPoint.x rPointY = rPointY - dragingBlockPoint.y BlockHelper.replaceBlock(pm, block, newBoardId, new Point(rPointX, rPointY)) } /** 移动小板 自由移动 */ static replaceBlock(pm: PlaceMaterial, block: PlaceBlock, newBoardId: number, p: Point) { let oldBoardId = block.boardId let isChangeBoard = block.boardId != newBoardId if (oldBoardId > pm.boardList.length) { oldBoardId = 1 } if (newBoardId > pm.boardList.length) { newBoardId = 1 } let pb_org = getPlaceBoard(pm, oldBoardId) let pb_new = getPlaceBoard(pm, newBoardId) pb_org.isCreateRemainSpace = true pb_new.isCreateRemainSpace = true let orgPlaceX = block.placeX let orgPlaceY = block.placeY let list = pb_new.blockList let maxPlaceId = ArrayExt.max(list, t => t.placeId, t => true, 0) + 1 let newPlaceId = maxPlaceId++ // 设置block block.boardId = newBoardId block.placeId = newPlaceId block.placeX = p.x block.placeY = p.y block.isAutoPlaced = false if (isChangeBoard) { ArrayExt.remove(pb_org.blockList, block) pb_new.blockList.push(block) } if (isChangeBoard) { pb_org.blockList = pb_org.blockList.filter(b => b.blockId != block.blockId) for (let board of pm.boardList) { if (board.boardId == oldBoardId) { board = pb_org continue } } // pm.boardList[oldBoardId] = pb_org checkOverlapInBoard(pm, pb_org) resetPlaceBoard(pm, pb_org) } checkOverlapInBoard(pm, pb_new) resetPlaceBoard(pm, pb_new) resetPlaceMaterial(pm) } /** 开始拖动时,获得板上的停靠点 */ static getDragingPointInBlock(block: PlaceBlock, mousePos: Point): BlockBorderPoint { let dis = Number.MAX_VALUE let point: Point let index = -1 // 基于小板排版基点的 鼠标坐标 let rx = mousePos.x - block.placeX let ry = mousePos.y - block.placeY // 算出 最近的拖拉点 let curves = BlockPlus.getBorder_moving(block) for (let i = 0; i < curves.length; i++) { let line = curves[i] let d = Math.pow(line.StartPoint.m_X + block.placeX - mousePos.x, 2) + Math.pow(line.StartPoint.m_Y + block.placeY - mousePos.y, 2); if (d < dis) { point = new Point(line.StartPoint.m_X, line.StartPoint.m_Y) dis = d index = i } } // 存在板外 的造型或2v刀路 if (BlockPlus.hasModelOutBlock(block)) { let pl = BlockPlus.borderToPolyline(curves, true) let x1 = pl.BoundingBox.min.x let y1 = pl.BoundingBox.min.y let x2 = pl.BoundingBox.max.x let y2 = pl.BoundingBox.max.y if (point.x < 0) point.x = x1 if (point.x > block.placeWidth) point.x = x2 if (point.y < 0) point.y = y1 if (point.y > block.placeLength) point.y = y2 // //拖拉死角,用偏移后的 // if(point.X < 0 && point.Y < 0) //左下角 // { // if(Math.abs(point.X -x1 ) < 40 ) point.X = x1; // if(Math.abs(point.Y -y1 ) < 40 ) point.Y = y1; // } // else if(point.X>block.PlaceWidth && point.Y < 0) //右下角 // { // if(Math.abs(point.X -x2 ) < 40 ) point.X = x2; // if(Math.abs(point.Y -y1 ) < 40 ) point.Y = y1; // } // else if(point.X>block.PlaceWidth && point.Y > block.PlaceLength ) // { // if(Math.abs(point.X -x2 ) < 40 ) point.X = x2; // if(Math.abs(point.Y -y2 ) < 40 ) point.Y = y2; // } // else if(point.X<0 && point.Y > block.PlaceLength) // { // if(Math.abs(point.X -x1 ) < 40 ) point.X = x1; // if(Math.abs(point.Y -y2 ) < 40 ) point.Y = y2; // } } // 找出 距 小板 dis = Number.MAX_VALUE let point_base: Point let curves_cut = BlockPlus.getBorder_sameKnife(block) for (let i = 0; i < curves_cut.length; i++) { let line = curves_cut[i] let d = Math.pow(line.StartPoint.m_X + block.placeX - mousePos.x, 2) + Math.pow(line.StartPoint.m_Y + block.placeY - mousePos.y, 2); if (d < dis) { point_base = new Point(line.StartPoint.m_X, line.StartPoint.m_Y) dis = d index = i } } let apexId = BlockHelper.getApexAngleNumFromBlock(block, point) return new BlockBorderPoint(block, point.x, point.y, index, apexId, point_base.x, point_base.y) } /** 拖动时,寻找停靠点最近的板和参照点 */ static getClosestBlock(pm: PlaceMaterial, pb: PlaceBoard, block: PlaceBlock, p: Point): BlockBorderPoint { let bestDis = Number.MAX_VALUE let closestBlock: PlaceBlock // 最接近的小板 let curveIndex = 0 let x = 0; let y = 0 // 最接近小板的接触点 坐标(现对于小板的位置) // 1先判断是否把停靠点拉到大板的四个点 let border = pm.cutBorder - pm.diameter / 2 - pm.cutKnifeGap / 2 // 因为移动小板的轮廓 是包括缝隙的一半 ,所以这边要抵消掉。 if (p.x < border + 50 && p.y < border + 50) return new BlockBorderPoint(null, border, border, -1, -1); if (p.x > pb.width - 50 && p.y < border + 50) return new BlockBorderPoint(null, pb.width - border, border, -1, -1); if (p.x > pb.width - 50 && p.y > pb.length - 50) return new BlockBorderPoint(null, pb.width - border, pb.length - border, -1, -1); if (p.x < border + 50 && p.y > pb.length - 50) return new BlockBorderPoint(null, border, pb.length - border, -1, -1); let innerBlocks = BlockHelper.getInnerBlock(block, pb.blockList) // 内部的小板 // 2找最靠近的板顶点(包括内部被造型挖掉的顶点) for (let b of pb.blockList) { if (b == block) continue // 这个板在block 内部,不参与对比 if (innerBlocks.includes(b)) continue let border = BlockPlus.getBorder_moving(b) let borders_inner = BlockPlus.getInnerPlaceBorders(b) // 在外框+内部内框内找到点 let borders = [] borders.push(border) for (const b of borders_inner) { borders.push(b) } for (const curves of borders) { for (let i = 0; i < curves.length; i++) { let line = curves[i] let dis = Math.pow(b.placeX + line.StartPoint.m_X - p.x, 2) + Math.pow(b.placeY + line.StartPoint.m_Y - p.y, 2); if (dis < 5000 && dis < bestDis) { bestDis = dis x = line.StartPoint.m_X y = line.StartPoint.m_Y curveIndex = i closestBlock = b } } } } if (closestBlock != null) { const point = new Point(x, y) let apexId = BlockHelper.getApexAngleNumFromBlock(closestBlock, point) // 考虑 closestBlock 有微小突出造型,加以偏移 const curves = BlockPlus.getBorder_moving(closestBlock) // 存在板外 的造型或2v刀路 if (BlockPlus.hasModelOutBlock(closestBlock)) { let pl = BlockPlus.borderToPolyline(curves, true) let x1 = pl.BoundingBox.min.x let y1 = pl.BoundingBox.min.y let x2 = pl.BoundingBox.max.x let y2 = pl.BoundingBox.max.y if (point.x < 0) point.x = x1 if (point.x > closestBlock.placeWidth) point.x = x2 if (point.y < 0) point.y = y1 if (point.y > closestBlock.placeLength) point.y = y2 } return new BlockBorderPoint(closestBlock, point.x, point.y, curveIndex, apexId) } // 3找不到最靠近的板 看看是否靠近大板四边 if (p.x < border + 50) return new BlockBorderPoint(null, border, p.y, -1, -1) if (p.x > pb.width - 50) return new BlockBorderPoint(null, pb.width - border, p.y, -1, -1) if (p.y < border + 50) return new BlockBorderPoint(null, p.x, border, -1, -1) if (p.y > pb.length - 50) return new BlockBorderPoint(null, p.x, pb.length - border, -1, -1) // 没找到附近可参考的板 return null } /** 选择最近的板,来定位被移动小板的位置 */ static replaceBlockRefClosest(pm: PlaceMaterial, block: PlaceBlock, newBoardId: number, dragingBlockPoint: BlockBorderPoint, referBlockPoint: BlockBorderPoint, dragedDistance: Point) { let gap = pm.diameter + pm.cutKnifeGap // 拖拉点现在位置 let dragedPointX = dragingBlockPoint.placeX + dragedDistance.x let dragedPointY = dragingBlockPoint.placeY + dragedDistance.y // 板的当前外扩 let blockoff = BlockSizePlus.getOffDis(block) let newP: Point let nx = 0 let ny = 0 // 参照点 为大板的四个顶点 if (referBlockPoint.block == null) { nx = referBlockPoint.x ny = referBlockPoint.y // block 定位坐标 < 拖拉点 偏移> nx = nx - dragingBlockPoint.x ny = ny - dragingBlockPoint.y } else { // 实际停靠点 坐标 nx = referBlockPoint.block.placeX + referBlockPoint.x ny = referBlockPoint.block.placeY + referBlockPoint.y // block 定位坐标 < 拖拉点 偏移> nx = nx - dragingBlockPoint.x ny = ny - dragingBlockPoint.y } // 默认按P定位 BlockHelper.replaceBlock(pm, block, newBoardId, new Point(nx, ny)) } /** 获得放置在block内部的板列表 */ static getInnerBlock(block: PlaceBlock, list: PlaceBlock[]): PlaceBlock[] { let innerList: PlaceBlock[] = [] // 如果没有内部空间直接范围 let borders = BlockPlus.getBorders_inner(block) if (!(borders && borders.length > 0)) return innerList for (let b of list) { if (b == block) continue let p1 = new Point(b.placeX, b.placeY) let p2 = new Point(b.placeX + b.placeWidth, b.placeY + b.placeLength) if (BlockHelper.isPointInInnerSpace(p1, block) && BlockHelper.isPointInInnerSpace(p2, block)) { innerList.push(b) continue } } return innerList } static findIdx(arr, target) { return arr.findIndex(c => c.blockId == target.blockId) } /** 删除小板 */ static removeBlock(order: PlaceOrder, pm: PlaceMaterial, pb: PlaceBoard, block: PlaceBlock) { console.log('移除前', order.blockList, pm.blockList, pb.blockList, 'block', block); if (block.isAdditionalBlock == false && block.isRemainBlock == false && [0, 1, 2].includes(block.type)) throw new Error('该板不能删除') console.log('移除前', order.blockList, pm.blockList, pb.blockList, 'block', block); // ArrayExt.remove(order.blockList, block); // ArrayExt.remove(pm.blockList, block); // ArrayExt.remove(pb.blockList, block); order.blockList.splice(this.findIdx(order.blockList, block), 1); pm.blockList.splice(this.findIdx(pm.blockList, block), 1); pb.blockList.splice(this.findIdx(pb.blockList, block), 1); console.log('移除后', order.blockList, pm.blockList, pb.blockList, 'block', block); //检查干涉 checkOverlapInBoard(pm, pb); //重设汇总 resetPlaceBoard(pm, pb); resetPlaceMaterial(pm); } /** 订单中添加余料板 */ static createRemainBlock(order: PlaceOrder, pm: PlaceMaterial, pb: PlaceBoard, binfo: BlockPlaceInfo) { let block = new PlaceBlock() let [info] = binfo.abInfo block.isRemainBlock = true block.blockName = '余料板' block.width = info.width block.length = info.length block.area = info.width * info.length * 0.000001 block.sealLeft = 0 block.sealRight = 0 block.sealTop = 0 block.sealBottom = 0 block.cutWidth = info.width block.cutLength = info.length block.cutArea = block.area block.texture = info.texture block.placeHole = 2 block.thickness = pm.thickness block.goodsId = pm.goodsId block.blockNo = binfo.bo block.blockId = Number.parseInt(binfo.bo) block.orderId = 0 if (binfo.points && binfo.points.length > 0) { let bdetail = new PlaceBlockDetail() bdetail.points = binfo.points bdetail.orgPoints = JSON.parse(JSON.stringify(binfo.points)) bdetail.isUnRegular = true bdetail.cutWidth = block.width bdetail.cutLength = block.length order.blockDetailList.push(bdetail) block.blockDetail = bdetail } let saleorder = order.orderList.find(t => t.orderId == 0) if (saleorder == null) { saleorder = new Order() order.orderList.push(saleorder) } block.placeOrder = order block.order = saleorder block.placeMaterial = pm order.blockList.push(block) pm.blockList.push(block) if (pb) pb.blockList.push(block) return block } /** 获得排序ID的位置 */ static getCutOrderPoint(block: PlaceBlock): Point { // return this.GetPlaceXYInBoard(block, block.SaleBlockDetail.notePosX, block.SaleBlockDetail.notePosY); return new Point(block.placeX + block.labelPosX, block.placeY + block.labelPosY) } static getBackPlaceStyle(placeStype: PlaceStyle): PlaceStyle { console.log('getBackPlaceStyle') // 正面=0,正面右转=1,正面后转=2,正面左转=3,反面=4,反面右转=5,反面后转=6,反面左转=7 if (placeStype == PlaceStyle.FRONT) return PlaceStyle.BACK if (placeStype == PlaceStyle.FRONT_TURN_RIGHT) return PlaceStyle.BACK_TURN_LEFT if (placeStype == PlaceStyle.FRONT_TURN_BACK) return PlaceStyle.BACK_TURN_BACK if (placeStype == PlaceStyle.FRONT_TURN_LEFT) return PlaceStyle.BACK_TURN_RIGHT if (placeStype == PlaceStyle.BACK) return PlaceStyle.FRONT if (placeStype == PlaceStyle.BACK_TURN_LEFT) return PlaceStyle.FRONT_TURN_RIGHT if (placeStype == PlaceStyle.BACK_TURN_BACK) return PlaceStyle.FRONT_TURN_BACK if (placeStype == PlaceStyle.BACK_TURN_RIGHT) return PlaceStyle.FRONT_TURN_LEFT return placeStype } // 开料面排钻, 造型, 是否双面开料---------------------------------------------- /** 重设开料正方面孔造型列表 */ /** * * @param block * @param config * config.processMode 加工模式(0开料机(雕刻机)加工 1开料机CNC组合 2定制加工) * config.isCutProcess 开料机(雕刻机)加工 */ static resetDoFace_HoleModel(block: PlaceBlock, config) { // //开料机加工模式: 0全加工 1不加工(特殊板除外) 2加工多的一面(特殊版都加工) 3加工少的一面(特殊版都加工) 4编程模式 5高级模式 // let processMode = PlaceStore.sysConfig.processMode; const { processMode = 0, isCutProcess = true, isCutAndCNCProcess = false, isCustomized = false } = config if (!block.blockDetail) { console.log('resetDoFace_HoleModel:block.blockDetail is undefind, please chck') return } let isTurnOver = block.isTurnOver() // 模式0: 开料机全部处理 if (isCutProcess) { if (!block.blockDetail) { console.error('') } // 正面 排钻 let faceHoles = isTurnOver ? block.blockDetail.holeListFaceB : block.blockDetail.holeListFaceA block.holeListFaceA = faceHoles.concat(block.blockDetail.holeListThrough) // 反面 排钻 block.holeListFaceB = isTurnOver ? block.blockDetail.holeListFaceA : block.blockDetail.holeListFaceB // 正面 造型 let faceModels = isTurnOver ? block.blockDetail.modelListFaceB : block.blockDetail.modelListFaceA block.modelListFaceA = faceModels.concat(block.blockDetail.modelListThrough) // 反面造型 block.modelListFaceB = isTurnOver ? block.blockDetail.modelListFaceA : block.blockDetail.modelListFaceB } else if (isCutAndCNCProcess) { NcAdvanceHelper.changeDoFace(block); let orgMA = block.blockDetail.modelListFaceA.filter(t => t.isCutting); let orgMB = block.blockDetail.modelListFaceB.filter(t => t.isCutting); let orgMT = block.blockDetail.modelListThrough.filter(t => t.isCutting); let orgHA = block.blockDetail.holeListFaceA.filter(t => t.isCutting); let orgHB = block.blockDetail.holeListFaceB.filter(t => t.isCutting); let orgHT = block.blockDetail.holeListThrough.filter(t => t.isCutting); if (isTurnOver) { block.modelListFaceA = orgMB.concat(orgMT); block.modelListFaceB = orgMA; block.holeListFaceA = orgHB.concat(orgHT); block.holeListFaceB = orgHA; } else { block.modelListFaceA = orgMA.concat(orgMT); block.modelListFaceB = orgMB; block.holeListFaceA = orgHA.concat(orgHT);; block.holeListFaceB = orgHB; } } else if (isCustomized) { //正面 排钻 let faceHoles = isTurnOver ? block.blockDetail.holeListFaceB : block.blockDetail.holeListFaceA; block.holeListFaceA = faceHoles.concat(block.blockDetail.holeListThrough); block.holeListFaceA = block.holeListFaceA.filter(t => t.isCutting); //反面 排钻 block.holeListFaceB = isTurnOver ? block.blockDetail.holeListFaceA : block.blockDetail.holeListFaceB; block.holeListFaceB = block.holeListFaceB.filter(t => t.isCutting); //正面 造型 let faceModels = isTurnOver ? block.blockDetail.modelListFaceB : block.blockDetail.modelListFaceA; block.modelListFaceA = faceModels.concat(block.blockDetail.modelListThrough); block.modelListFaceA = block.modelListFaceA.filter(t => t.isCutting); //反面造型 block.modelListFaceB = isTurnOver ? block.blockDetail.modelListFaceA : block.blockDetail.modelListFaceB; block.modelListFaceB = block.modelListFaceB.filter(t => t.isCutting); } //重设 isDO block.blockDetail.holes.forEach(t => t.isCutting = false); block.blockDetail.models.forEach(t => t.isCutting = false); block.holeListFaceA.forEach(t => t.isCutting = true); block.holeListFaceB.forEach(t => t.isCutting = true); block.modelListFaceA.forEach(t => t.isCutting = true); block.modelListFaceB.forEach(t => t.isCutting = true); //修改了默认加工,需要再对造型换刀处理 resetModelKnife(block, config); //B面是否需要加工 block.isCutOtherFace = block.blockDetail.holeListFaceB.length + block.blockDetail.modelListFaceB.length > 0; //需翻面处理(包括开料机,cnc) block.isCutTurnOver = block.isCutOtherFace; //反面需处理(包括开料机,cnc) by origin // if (!block.IsTurnOver) // { // block.NeedTurnFaceToDo = block.BackHoleCount + block.BackModelCount + block.HoleCount_Side > 0; // } //获取贴标位置 let p = this.getPlaceXYInBlock(block, block.blockDetail.labelPosX, block.blockDetail.labelPosY, false, false); block.labelPosX = p.x; block.labelPosY = p.y; //设置 cnc 处理面 this.resetCncIsDoFace(block); } /** 重设其他 */ static restOther(block) { //B面是否需要加工 block.isCutOtherFace = block.blockDetail.holeListFaceB.length + block.blockDetail.modelListFaceB.length > 0; //需翻面处理(包括开料机,cnc) block.isCutTurnOver = block.isCutOtherFace; //获取贴标位置 let p = this.getPlaceXYInBlock(block, block.blockDetail.labelPosX, block.blockDetail.labelPosY, false, false); block.labelPosX = p.x; block.labelPosY = p.y; //设置 cnc 处理面 this.resetCncIsDoFace(block); } /** 开料面排钻列表 */ static getHoles_DoFace(block: PlaceBlock, isBackFace: boolean): BlockHole[] { if (!block.blockDetail) { console.log('getHoles_DoFace:blockDetail is undefind!') return [] } let holesArr = isBackFace ? block.blockDetail?.holes.filter(e => e.face == 1) : block.blockDetail?.holes.filter(e => e.face == 0) // 给孔 加上所属的板编号 holesArr.map(e => e.blockNo = block.blockNo) return holesArr } /** 获取开料大板内所有的排钻 未排序*/ static async GetHoles_BoardAllBlocksByDoFace(pb: PlaceBoard,isBackFace: boolean) { let allHoles: any[] = [] // const backPlaceStyleArr = [PlaceStyle.BACK, PlaceStyle.BACK_TURN_BACK, PlaceStyle.BACK_TURN_LEFT, PlaceStyle.BACK_TURN_RIGHT] for (const block of pb.blockList) { let holes = await this.getHoles_DoFace(block, isBackFace) allHoles = allHoles.concat(holes) } return allHoles } /** 开料面造型列表 */ static GetModels_DoFace(block: PlaceBlock, isBackFace: boolean): BlockModel[] { if (!block.blockDetail) { console.log('getHoles_DoFace:blockDetail is undefind!') return [] } let modelsArr = isBackFace ? block.blockDetail?.models.filter(e => e.face == 1) : block.blockDetail?.models.filter(e => e.face == 0) // 给造型 加上所属的板编号 modelsArr.map(e => e.blockNo = block.blockNo) return modelsArr } static async GetModels_BoardAllBlocksByDoFace(pb: PlaceBoard,isBackFace: boolean) { let allModels: any[] = [] const backPlaceStyleArr = [PlaceStyle.BACK, PlaceStyle.BACK_TURN_BACK, PlaceStyle.BACK_TURN_LEFT, PlaceStyle.BACK_TURN_RIGHT] for (const block of pb.blockList) { let models = await this.GetModels_DoFace(block, isBackFace) allModels = allModels.concat(models) } return allModels } // 判断造型是否打穿且矩形 static checkModelIsThroughRectange(block: PlaceBlock, m: BlockModel): boolean { if (m.depth < block.thickness - 0.01) return false if (m.pointList.length != 5) return false let p0 = m.pointList[0] let p1 = m.pointList[1] let p2 = m.pointList[2] let p3 = m.pointList[3] let p4 = m.pointList[4] // 有曲线,不算 if (p0.curve != 0 || p1.curve != 0 || p2.curve != 0 || p3.curve != 0 || p4.curve != 0) return false // 不是闭合的,不算矩形 if (!equal(p0.pointX, p4.pointX) || !equal(p0.pointY, p4.pointY)) return false // 有边都斜线 ,就不算矩形 if (!equal(p0.pointX, p1.pointX) && !equal(p0.pointY, p1.pointY)) return false if (!equal(p1.pointX, p2.pointX) && !equal(p1.pointY, p2.pointY)) return false if (!equal(p2.pointX, p3.pointX) && !equal(p2.pointY, p3.pointY)) return false if (!equal(p3.pointX, p4.pointX) && !equal(p3.pointY, p4.pointY)) return false // 对角线 不想等,不算 let d1 = (p0.pointX - p2.pointX) * (p0.pointX - p2.pointX) + (p0.pointY - p2.pointY) * (p0.pointY - p2.pointY) let d2 = (p1.pointX - p3.pointX) * (p1.pointX - p3.pointX) + (p1.pointY - p3.pointY) * (p1.pointY - p3.pointY) if (Math.abs(d1 - d2) > 0.5) return false return true } // 判断孔是打穿的面孔 static isHoleThrough(block: PlaceBlock, hole: BlockHole): boolean { if (hole.face == FaceType.SIDE) return false if (hole.holeType == HoleType.THROUGH_HOLE) return true if (hole.depth >= block.thickness) return true return false } // 翻面标签开料面 是否需处理<标签显示>-------------------------------------------- /** 计算 cnc 正面,翻面是否应该处理 */ static resetCncIsDoFace(block: PlaceBlock) { // remove by yonnie // //开料机加工模式: 0全加工 1不加工(特殊板除外) 2加工多的一面(特殊版都加工) 3加工少的一面(特殊版都加工) 4编程模式 5高级模式 // let roleNum = PlaceStore.sysConfig.IsPriorFacing_RoleNum; // 模式1: 开料机默认全部排钻造型 (正反面全部) if (PlaceStore.sysConfig.isCutProcess) { block.isCncLabelA = false block.isCncLabelB = false block.isCncLabelTurnOver = block.holeCountFaceB + block.modelCountFaceB > 0 return } // 其他模式 block.isCncLabelA = false block.isCncLabelB = false // 侧孔 block.isCncLabelTurnOver = block.holeCountSide + (block.isTurnOver ? block.holeCountFront + block.modelCountFront : block.holeCountBack + block.modelCountBack) > 0 return } // 开料时下刀点,下刀路径相关-------------------------------------------------- /** 获得下刀点在边框线上的坐标 */ static getCutPoint(block: PlaceBlock): Point { let curves = BlockPlus.getBorder(block) let pnum = block.cutPointId while (pnum < 0) { pnum += curves.length } while (pnum >= curves.length) { pnum -= curves.length } return new Point(curves[pnum].StartPoint.m_X, curves[pnum].StartPoint.m_Y) } /** 获得下刀点在大板上的显示红点坐标 */ static getCutPointXYInBoard(block: PlaceBlock): Point { let p = this.getCutPoint(block) let x = p.x let y = p.y let offset = 4 // 靠近板心 距离 x = (x < block.placeWidth * 0.5) ? x + offset : x - offset y = (y < block.placeLength * 0.5) ? y + offset : y - offset return new Point(block.placeX + x, block.placeY + y) } /** 获得下刀线,下刀点前一段线 */ static getCutLine_Prev(block: PlaceBlock, borders: Curve2d[], offValue: number, prevLength = 10): Curve2d { let p = this.getCutPoint(block) let minDis = Number.MAX_VALUE let index = 0 for (let i = 0; i < borders.length; i++) { let x0 = borders[i].StartPoint.m_X - p.x let y0 = borders[i].StartPoint.m_Y - p.y let dis = x0 * x0 + y0 * y0 if (dis < minDis) { minDis = dis index = i } } let prevID = index - 1 if (prevID < 0) prevID = prevID + borders.length let prevCurve = borders[prevID] if (prevCurve instanceof Line2d) { if (prevCurve.m_Length < prevLength) { let newID = index - 2 if (newID < 0) newID = newID + borders.length let newC = borders[newID] if (newC instanceof Line2d) { if (newC.m_Length > prevLength) return newC } } return prevCurve } let arc = prevCurve as Arc2d if (Math.abs(arc.m_Radius - offValue) < 0.2) { // 这是倒角,返回 再前一段作为下刀线 let prevID = index - 2 if (prevID < 0) prevID = prevID + borders.length return borders[prevID] } else { // 不是倒角,鬼知道之前是什么东西,就返回这条了. return arc } } // 获得下一条线段 static getCutLine_Next(borders: Curve2d[], line: Curve2d): Curve2d { let index = borders.indexOf(line) index++ if (index == borders.length) { index = 0 } return borders[index] } // 坐标相关 ,判断点在板内, 转换坐标等-------------------------------------------- /** 获得点在小板的顶角序号 左下角0,右下角1,右上角2,左上角3 不是顶角-1 */ static getApexAngleNumFromBlock(block: PlaceBlock, p: Point) { let areaID = -1 if (equal(p.x, 0) && equal(p.y, 0)) return 0 if (equal(p.x, block.placeWidth) && equal(p.y, 0)) return 1 if (equal(p.x, block.placeWidth) && equal(p.y, block.placeLength)) return 2 if (equal(p.x, 0) && equal(p.y, block.placeLength)) return 3 return -1 } // 判断点是否在板内,isOffset 是否外扩 刀直径 static isPointInBlock(p: Point, block: PlaceBlock, isOffset: boolean = false): boolean { let offValue = isOffset ? block.blockDetail.offsetKnifeRadius : 0 // 如果 点 直接在异形的所在的矩形外,表示不在异形内,直接返回false if (p.x < block.placeX - offValue) return false if (p.x > block.placeX + block.placeWidth + offValue) return false if (p.y < block.placeY - offValue) return false if (p.y > block.placeY + block.placeLength + offValue) return false let x = p.x - block.placeX let y = p.y - block.placeY let bpl = isOffset ? BlockPlus.getOrgPloylines(block) : BlockPlus.getCutPloylines(block) if (!bpl) return false let isIn = PolylineHelper.isPointInPolyline(bpl.pl, x, y) if (isIn == false) return false for (let mpl of bpl.pls_inner) { let isInModel = PolylineHelper.isPointInPolyline(mpl, x, y) if (isInModel) return false // 如果在造型洞里头 } return true } // 判断点是否在板内空间里头(造型挖空的) static isPointInInnerSpace(p: Point, block: PlaceBlock) { // 判断是否在内部空间里头,则返回false; let borders_inner = BlockPlus.getCutLines_inner(block) if (borders_inner && borders_inner.length > 0) { for (const border of borders_inner) { // 内部空间 有四个边 let xs = border.map((t) => { return t.StartPoint.m_X }) let ys = border.map((t) => { return t.StartPoint.m_X }) let x0 = Math.min.apply(null, xs) let x1 = Math.max.apply(null, xs) let y0 = Math.min.apply(null, ys) let y1 = Math.max.apply(null, ys) if (p.x >= block.placeX + x0 && p.x <= block.placeX + x1 && p.y >= block.placeY + y0 && p.y <= block.placeY + y1) return true } } return false } /** 获得原坐标在放置后的新坐标 */ static getPlaceXYInBlock(block: PlaceBlock, x: number, y: number, isSealed: boolean, isFaceB = false, preCutValueOff = null): Point { let bwidth = block.cutWidth let blength = block.cutLength let x0 = x let y0 = y if (isSealed) // 已封边 { bwidth = block.width blength = block.length x0 += block.offsetX y0 += block.offsetY } if (!isSealed && preCutValueOff) // 没封边,且有封边 { bwidth += preCutValueOff.w blength += preCutValueOff.l x0 += preCutValueOff.x y0 += preCutValueOff.y } let _point: any = BlockHelper.getPlacedPostionInBlock(block.placeStyle, bwidth, blength, x0, y0, isFaceB) return _point } /** 获得原板内坐标在大板中的坐标 */ static getPlaceXYInBoard(block: PlaceBlock, x: number, y: number, isSealed = false): Point { // 正面 let pos0 = BlockHelper.getPlaceXYInBlock(block, x, y, isSealed, false) pos0.x += block.placeX pos0.y += block.placeY return pos0 } /** 获得翻转后的新坐标 */ static getPlacedPostionInBlock(placeStyle: PlaceStyle, bwidth: number, blength: number, x0: number, y0: number, isFaceB: boolean): Point { let posX = x0 let posY = y0 let placeWidth = bwidth switch (placeStyle) { case PlaceStyle.FRONT: break case PlaceStyle.FRONT_TURN_RIGHT: posX = y0 posY = bwidth - x0 placeWidth = blength break case PlaceStyle.FRONT_TURN_BACK: posX = bwidth - x0 posY = blength - y0 break case PlaceStyle.FRONT_TURN_LEFT: posX = blength - y0 posY = x0 placeWidth = blength break case PlaceStyle.BACK: posX = bwidth - x0 posY = y0 break case PlaceStyle.BACK_TURN_RIGHT: posX = y0 posY = x0 placeWidth = blength break case PlaceStyle.BACK_TURN_BACK: posX = x0 posY = blength - y0 break case PlaceStyle.BACK_TURN_LEFT: posX = blength - y0 posY = bwidth - x0 placeWidth = blength break default: break } if (isFaceB) { posX = placeWidth - posX } return new Point(posX, posY) } /** 获得翻转前 小板内原坐标 posX,posY 放置后的坐标 */ static getOrginalPositionInBlock(block: PlaceBlock, placeStyle: PlaceStyle, posX: number, posY: number): Point { let x0 = posX let y0 = posY let bwidth = block.cutWidth let blength = block.cutLength switch (placeStyle) { case PlaceStyle.FRONT: break case PlaceStyle.FRONT_TURN_RIGHT: y0 = posX x0 = bwidth - posY break case PlaceStyle.FRONT_TURN_BACK: x0 = bwidth - posX y0 = blength - posY break case PlaceStyle.FRONT_TURN_LEFT: y0 = blength - posX x0 = posY break case PlaceStyle.BACK: x0 = bwidth - posX y0 = posY break case PlaceStyle.BACK_TURN_RIGHT: y0 = posX x0 = posY break case PlaceStyle.BACK_TURN_BACK: x0 = posX y0 = blength - posY break case PlaceStyle.BACK_TURN_LEFT: y0 = blength - posX x0 = bwidth - posY break default: break } return new Point(x0, y0) } /** 获得离点距离最近的边框序号 faceId */ static getClosestSideFaceID(bDetail: PlaceBlockDetail, x3: number, y3: number): number { let index = 0 let minDis = 99999 for (let i = 0; i < bDetail.points.length; i++) { let j = i + 1 if (i == bDetail.points.length - 1) j = 0 let x1 = bDetail.points[i].pointX let y1 = bDetail.points[i].pointY let x2 = bDetail.points[j].pointX let y2 = bDetail.points[j].pointY let dis = CADExt.getDisOff(x1, y1, x2, y2, x3, y3) if (dis < minDis) { minDis = dis index = i } } return index } /** 获得造型 反向点阵 */ static getModelPoints(model: BlockModel, isTurn: boolean): BlockModelPoint[] { let orgPoints = model.pointList if (isTurn == false) return orgPoints return BlockHelper.getTurnedModelPoints(orgPoints) } static getTurnedModelPoints(orgPoints: BlockModelPoint[]) // 造型翻转 { let newPoints = [] for (let i = orgPoints.length - 1; i >= 0; i--) { let prev = i > 0 ? i - 1 : orgPoints.length - 1 let newPoint = orgPoints[i].copy() newPoint.curve = -orgPoints[prev].curve newPoint.radius = orgPoints[prev].radius newPoints.push(newPoint) } return newPoints } static getTurnPoints(orgPoints): any[] { let newPoints = [] for (let i = orgPoints.length - 1; i >= 0; i--) { let p = orgPoints[i] let p_prev = i > 0 ? orgPoints[i - 1] : orgPoints[orgPoints.length - 1] let newP = { x: p.x, y: p.y, z: p.z, bul: p_prev.bul, r: p_prev.r } newPoints.push(newP) } return newPoints } static getRadius(x1: number, y1: number, x2: number, y2: number, bul: number): number { let d = Math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2) / 2 return 0.5 * d * (1 + bul ** 2) / bul } }