import { StringFormat } from "./handleAbility/common/base/StringFormat" import type * as CAD from './handleAbility/common/base/CAD' import { Polyline } from "cadapi" import { ArrayExt } from "./handleAbility/common/ArrayExt" /**配置项属性 */ export class confItem { /** 属性key */ key: string /** 说明 */ label: string /** 属性value 值 */ value: Array | any } /** 内部指令 接收 */ export class CodeAction { code?: String order?: String codeParams?: any } /**内部响应类 */ export class GCodeResType { code: number = -1 data: any = null msg: string = '' logError(msg) { console.error(msg) } } /** 排孔类型 */ export enum HoleArrange { /** 正面 */ FRONT = 0, /** 反面 */ BACK = 1, /** 随意面 */ RANDOM_FACE = 2, } // 加工项 点数据 export class CodeParams { /** x坐标 */ x?: Number | String /** y坐标 */ y?: Number | String /** z坐标 */ z?: Number | String /** 调用的代码编号 */ dir?: Number | String /** 圆弧半径 */ r?: Number | String /** 速度 */ f?: Number | String /** IJK 模式的i */ i?: Number | String /** IJK 模式的j */ j?: Number | String /** IJK 模式的k */ k?: Number | String /** 代码标识 */ codeKey?: String /** x坐标 */ xKey?: String /** y坐标 */ yKey?: String /** z坐标 */ zKey?: String /** 圆弧半径 */ rKey?: String /** 速度 */ fKey?: String /** IJK 模式的i */ iKey?: String /** IJK 模式的j */ jKey?: String /** IJK 模式的k */ kKey?: String } export type _knifeType = Partial /** * 板面类型 * 0正面 1反面 2侧面 21左侧面 22右侧面 23上侧面 24下侧面 29 弧形侧面 30异形侧面 */ export enum FaceType { /** 正面 */ FRONT = 0, /** 反面 */ BACK = 1, /** 侧面 */ SIDE = 2, /** 左侧面 */ LEFT_SIDE = 21, /** 右侧面 */ RIGHT_SIDE = 22, /** 上侧面 */ TOP_SIDE = 23, /** 下侧面 */ BOTTOM_SIDE = 24, /** 弧形侧面 */ CURVED_SIDE = 29, /** 异形侧面 */ SPECIAL_SHAPED_SIDE = 30, /** 未设置 */ UNSET = -1 } /** 开料刀 */ export class Knife { /** 是否启用 */ isEnabled = true; /** 轴号 */ axleId = 0; /** 开料刀ID号 */ knifeId = 1; /** 加工面(0正面 1反面 2左侧面 3右侧面 4上侧面 5下侧面 6任意) */ processFace = 0; /** 刀名称 */ knifeName = ''; /** 刀具类型(1铣刀 2成型刀 3钻头 4锯 5刀片) */ knifeType = KnifeType.MILLING_CUTTER; /** 功能属性(数组): 1开料/切割 2拉槽 3铣型 4铣孔 5钻孔 6拉米诺 7乐扣 8T型 */ ability: any = []; // /** 默认开料刀 */ // isDefaultCutKnife = false; // /** 是否可用于开料切割 */ // isCuttingKnife = false; // /** 是否允许铣孔(knifeType为铣刀生效) */ // isMillingAllowed = false; /** 刀直径mm */ diameter = 6; /** 刀长(最大深度) */ length = 20; /** 锯齿厚度,单次加工切缝宽度 */ sawThiness = 0; /**锯向: 0横向(或长边) 1纵向(短边) 2自由角度*/ sawDirection = 0; /**切向加工方向: 0横向左往右 2横向右往左 3纵向上往下 4纵向下往上 5随意 */ processDirection = 0; /**进给速度, 0取系统默认 */ speed = 0; /** 进给深度 */ stepDepth = 0; // /** 组号 */ // groupNo = 0; // /** 主刀 */ // isMainKnife = false; // /** 是否高级加工 */ // isAdvancedProcessEnabled = false; // /** 是否集合加工 */ // isBatchProcessEnabled = false; // /** 副刀偏置长边偏移(Y轴) */ // auxKnifeOffsetY = 0; // /** 副刀偏置短边偏移(X轴) */ // auxKnifeOffsetX = 0; /** 偏置短边偏移(X轴)-相对于工件原点位置XY坐标的短边方向偏移量 */ offsetX = 0; /** 偏置长边偏移(Y轴) -相对于工件原点位置XY坐标的长边方向偏移量*/ offsetY = 0; /** 偏置垂直偏移(Z轴) -相对于工件原点位置XY坐标的垂直方向偏移量*/ offsetZ = 0; /** 基准坐标-短边(X轴) -钻头在钻包中短边方向(纵向)的相对位置 */ baseX = 0; /** 基准坐标-长边(Y轴) -钻头在钻包中长边方向(横向)的相对位置 */ baseY = 0; /**组合钻 */ isModularDrill = false; /** 是否预启动 */ isPreStartEnabled = false; /** 预启动提前动作数 */ preStartAheadActionCount = 5; /** 预启动延迟换刀 */ isPreStartToolChangeDelay = false; /** 预启动延迟换刀指令 */ preStartToolChangeDelayCode = ''; /** 轴启动指令后置 */ isAxisStartCodePostpost = false; /** 轴停止指令前置 */ isAxisStopCodePrepose = false; /** 钻组独立指令(启用后,刀起始指令、刀结束指令使用钻组起始指令、钻组结束指令替换) */ drillGroupCode = ''; /** 轴启动代码*/ axisStartCode = ""; /** 刀启动代码 */ knifeStartCode = ''; /** 钻组起始指令 */ drillGroupStartCode = ''; /** 钻组结束指令 */ drillGroupEndCode = ''; /** 刀停止代码 */ knifeStopCode = ''; /** 轴停止指令 */ axisStopCode = ''; // /** 高级加工指令 */ // advancedCode = ''; /** 开料刀 */ isCuttingKnife() { return this.isEnabled && this.ability.includes(AbilityType.CUT); } /** 造型刀 */ isModelingKnife() { return this.isEnabled && this.ability.includes(AbilityType.MILLING_MODEL); } /** 钻刀 */ isDrillingKnife() { return this.isEnabled && this.ability.includes(AbilityType.DRILL_HOLE); } /** 铣孔 */ isCutting4HoleKnife() { return this.isEnabled && this.ability.includes(AbilityType.MILLING_HOLE); } /** 设置刀具(轴号, 刀名, 刀直径, 是否主刀, 是否铣孔, 是否开料刀) */ // set(axleId: number, name: string, diameter: number, isMainKnife: boolean, isMillingAllowed: boolean, isCuttingKnife: boolean) /** 设置刀具(轴号, 刀名, 刀类型, 刀直径, 刀长, 是否默认刀) */ } /** 刀类型: MILLING_CUTTER铣刀 FORMING_CUTTER成型刀 DRILL钻头 SAW锯 BLADE刀片 */ export enum KnifeType { /** 铣刀 */ MILLING_CUTTER = 1, /** 成型刀 */ FORMING_CUTTER = 2, /** 钻头 */ DRILL = 3, /** 锯 */ SAW = 4, /** 刀片 */ BLADE = 5 } /** 刀功能: ** 1-CUT开料/切割 2-PULLING_GROOVE拉槽 3-MILLING_MODEL铣型 4-MILLING_HOLE铣孔 ** 5-DRILL_HOLE钻孔 6-RAMINO拉米诺 7-EASY_FASTEN乐扣 8-T_TYPE T型 */ export enum AbilityType { /** 1开料/切割 */ CUT = 1, /** 2拉槽 */ PULLING_GROOVE = 2, /** 3铣型 */ MILLING_MODEL = 3, /** 4铣孔 */ MILLING_HOLE = 4, /** 5钻孔 */ DRILL_HOLE = 5, /** 6拉米诺 */ RAMINO = 6, /** 7乐扣 */ EASY_FASTEN = 7, /** 8T型 */ T_TYPE = 8 } /** 枚举 坐标轴类型 */ export enum AxisType { /** X轴正 */ X_POS = 0, /** X轴负 */ X_NEG = 1, /** Y轴正 */ Y_POS = 2, /** Y轴负 */ Y_NEG = 3, /** 向上Z轴正 */ Z_POS = 4, /** 向下Z轴负 */ Z_NEG = 5, } /** 枚举 坐标轴类型 */ export enum OriginZPosition { /** 台面向上Z轴正 */ WorkTop = 0, /** 板面向上Z轴正 */ BoardFace = 1, } // nc文件编码 export const ncEncodeMap = { 'UTF-8': 'UTF-8', 'GB2312': 'GB2312', 'UTF-8-BOM': 'UTF-8-BOM', 'GBK': 'GBK', 'Big-5': 'Big-5', 'GB18030': 'GB18030', 'Unicode': 'Unicode' } // 小板文件名选项 export const smallPlateOptionsMap = { 板宽: '{0}', 板长: '{1}', 颜色: '{2}', 材质: '{3}', 大板号: '{4}', 工位号: '{5}', 板厚: '{6}', 开料顺序: '{7}', 批次识别: '{8}', 小板编号: '{9}', 全局大板号: '{10}', 品牌: '{11}', } // zip压缩包文件名选项 export const zipFileOptionsMap = { '板宽': '{0}', '板长': '{1}', '颜色': '{2}', '材质': '{3}', '大板号': '{4}', '工位号': '{5}', '板厚': '{6}', '开料顺序': '{7}', '批次识别': '{8}', '小板编号': '{9}', '全局大板号': '{10}', '品牌': '11', } /** 枚举 大板边角位置 */ export enum BoardPosition { /** 左上角 */ // LEFT_TOP = 0, // /** 左下角 */ // LEFT_BOTTOM = 1, // /** 右下角 */ // RIGHT_BOTTOM = 2, // /** 右上角 */ // RIGHT_TOP = 3, /** 左上角 */ LEFT_TOP = 3, /** 左下角 */ LEFT_BOTTOM = 0, /** 右下角 */ RIGHT_BOTTOM = 1, /** 右上角 */ RIGHT_TOP = 2, /** * 左下角 = 0, 右下角 = 1, 右上角 = 2, 左上角 = 3 */ } /** 排版样式 */ export enum PlaceStyle { /** 正面 */ FRONT = 0, /** 正面右转 */ FRONT_TURN_RIGHT = 1, /** 正面后转 */ FRONT_TURN_BACK = 2, /** 正面左转 */ FRONT_TURN_LEFT = 3, /** 反面 */ BACK = 4, /** 反面右转 */ BACK_TURN_RIGHT = 5, /** 反面后转 */ BACK_TURN_BACK = 6, /** 反面左转 */ BACK_TURN_LEFT = 7, } /** 小板边的位置类型 */ export enum EdgeType { /** 下=0 */ BOTTOM = 0, /** 右=1 */ RIGHT = 1, /** 上=2 */ TOP = 2, /** 左=3 */ LEFT = 3, } /** 开料小板 */ export class PlaceBlock { /** 小板明细(异形,孔,造型) */ blockDetail: PlaceBlockDetail | null = null // 订单信息---------------------------------------------------------- /** 订单号 */ orderId: number = 0 /** 板材ID */ goodsId = '' // 小板属性----------------------------------------------------------- // 房间名, 柜体名, 小板ID, 小板编号,小板名称, 板材名称, 备注 // 房间ID roomId = '' /** 房间名 */ roomName = '' /** 柜体号 */ bodyId = '' /** 柜体名 */ bodyName = '' /** 小板ID */ blockId = 0 /** 原小板ID */ oldBlockId: number = 0 /** 板编号 */ blockNo: number = 0 /** 自定义板编号 */ customPlateNo: any = '' /** 明细ID */ itemId: number = 0 /** 标签板号 */ labelNo = '' /** 板名称 */ blockName = '' /** 板件备注 */ plateRemark = '' /** 备注1 */ remark1 = '' /** 备注2 */ remark2 = '' /** 备注3 */ remark3 = '' /** 备注4 */ remark4 = '' /** 备注5 */ remark5 = '' /** 铰链备注 */ extraRemark: object = {} // 尺寸,封边,开料尺寸----------------------------------------------------- /** 板宽 */ width = 0 /** 板长 */ length = 0 /** 板厚 */ thickness = 0 /** 面积 Size */ area = 0 /** 左封边 BorderLeft */ sealLeft = 0 /** 右封边 BorderRight */ sealRight = 0 /** 上封边 BorderUpper */ sealTop = 0 /** 下封边 BorderUnder */ sealBottom = 0 /** 无封边板宽 开料板宽 CuttingWidth */ cutWidth = 0 /** 无封边板长 开料板长 CuttingLength */ cutLength = 0 /** 无封边面积 开料面积 CuttingSize */ cutArea = 0 // 高级------------------------------------------------------------- /** 自增小板 */ isAdditionalBlock = false /** 余料板 IsScrapBlock */ isRemainBlock = false /** 开料纹路 */ texture = TextureType.ROTATABLE_TEXTURE // 可翻转 /** 排版面 PaiKong */ placeHole = HoleArrange.RANDOM_FACE // 随意面 /** 异型偏移x BorderLengthHeavy */ abnormalOffsetX = 0 /** 异型偏移y BorderLengthLight */ abnormalOffsetY = 0 /** 正面有大孔 */ bigHoleInFaceA(): boolean { let res = false if (this.blockDetail && this.blockDetail.bigHoleInFaceA) { res = true } return res } /** 是否异形 */ isUnRegular = false // isUnRegular(): boolean { // return this.blockDetail && this.blockDetail.isUnRegular || false // } /** 正面孔数 */ holeCountFront(): number { return this.blockDetail && this.blockDetail.holeCountFront || 0 } /** 反面孔数 */ holeCountBack(): number { return this.blockDetail && this.blockDetail.holeCountBack || 0 } /** 通孔数 */ holeCountThrough(): number { return this.blockDetail && this.blockDetail.holeCountThrough || 0 } /** 侧孔数 HoleCount_Side */ holeCountSide(): number { return this.blockDetail && this.blockDetail.holeCountSide || 0 } /** 左侧孔数 HoleCount_Left */ holeCountLeft() { return this.blockDetail && this.blockDetail.holeCountLeft } /** 右侧孔数 HoleCount_Right */ holeCountRight() { return this.blockDetail && this.blockDetail.holeCountRight } /** 侧孔数 HoleCount_Upper */ holeCountTop() { return this.blockDetail && this.blockDetail.holeCountTop } /** 侧孔数 HoleCount_Under */ holeCountBottom() { return this.blockDetail && this.blockDetail.holeCountBottom } /** 正面造型数 */ modelCountFront(): number { return this.blockDetail && this.blockDetail.modelCountFront || 0 } /** 反面造型数 */ modelCountBack(): number { return this.blockDetail && this.blockDetail.modelCountBack || 0 } /** 打穿造型数 */ modelCountThrough(): number { return (this.blockDetail && this.blockDetail.modelCountThrough) || 0 } /** 有挖穿造型 */ hasModelThrough(): boolean { return (this.blockDetail && this.blockDetail.hasModelThrogh) || false } /** 需双面处理 */ isDoubleFaceProcess(): boolean { if (this.placeHole == HoleArrange.RANDOM_FACE) // 随意面 { return (this.blockDetail && this.blockDetail.isTwoFaceProcess) || false } else if (this.placeHole == HoleArrange.FRONT) // 正面 { return this.holeCountBack() + this.modelCountBack() > 0 } else { return this.holeCountFront() + this.modelCountFront() > 0 } } // (根据排版规格计算) /** 优化排版时,需反面(不是真正的反面开料) */ isTurnFaceToPlace = false /** 优化排版时,可双面排版 */ isTwoFaceToPlace = false /** 是否弧形地脚,不处理异形 IsHXDJX */ isCurvedGroundLine = false /** 封边偏移值x */ offsetX(): number { return (this.blockDetail && this.blockDetail.offsetX) || 0 } /** 封边偏移值y */ offsetY(): number { return (this.blockDetail && this.blockDetail.offsetY) || 0 } // 异形、孔、造型明细列表 points(): BlockPoint[] { return (this.blockDetail && this.blockDetail.points) || [] } orgPoints(): BlockPoint[] { return (this.blockDetail && this.blockDetail.orgPoints) || [] } holes(): BlockHole[] { return (this.blockDetail && this.blockDetail.holes) || [] } models(): BlockModel[] { return (this.blockDetail && this.blockDetail.models) || [] } holeListOrgFaceA(): BlockHole[] { return (this.blockDetail && this.blockDetail.holeListFaceA) || [] } holeListOrgFaceB(): BlockHole[] { return (this.blockDetail && this.blockDetail.holeListFaceB) || [] } holeListOrgThrough(): BlockHole[] { return (this.blockDetail && this.blockDetail.holeListThrough) || [] } holeListOrgFaceSide(): SideHole[] { return (this.blockDetail && this.blockDetail.holeListSide) || [] } modelListOrgFaceA(): BlockModel[] { return (this.blockDetail && this.blockDetail.modelListFaceA) || [] } modelListOrgFaceB(): BlockModel[] { return (this.blockDetail && this.blockDetail.modelListFaceB) || [] } modelListOrgTrough(): BlockModel[] { return (this.blockDetail && this.blockDetail?.modelListThrough) || [] } // 排版情况 /** 已排版 */ isPlaced = false /** 全局大板Id */ fullBoardId = 0 /** 大板ID */ boardId = 0 /** 排单ID */ placeId = 0 /** 坐标X */ placeX = 0 /** 坐标Y */ placeY = 0 /** 排版方式 */ placeStyle: PlaceStyle = PlaceStyle.FRONT // 正面 /** 下刀点区域 */ cutRegion = BlockRegion.LEFT_BOTTOM // 左下 /** 开料顺序 */ cutOrder = 0 /** 下刀点位 */ cutPointId = 0 /** 开料宽 */ placeWidth = 0 /** 开料长 */ placeLength = 0 /** 开料左封边 */ placeSealLeft = 0 /** 开料右封边 */ placeSealRight = 0 /** 开料上封边 */ placeSealTop = 0 /** 开料下封边 */ placeSealBottom = 0 /** 原造型下刀超出板外情况 OrgSizeOutOff */ orgSizeExpand: SizeExpand = new SizeExpand() /** 造型下刀超出板外情况 尺寸扩展 SizeOutOff */ sizeExpand() { return this.blockDetail ? this.blockDetail.currentSizeExpand : '' }; /** 排版宽 加上预铣等外括 ,开料刀半径 ,缝隙 */ // placeFullWidth() { return this.cutWidth + this.blockDetail.currentSizeExpand.width } placeFullWidth() { return this.cutWidth + (this.blockDetail ? this.blockDetail?.currentSizeExpand?.width || 0 : 0) } /** 排版长 加上预铣等外括 ,开料刀半径 ,缝隙 */ placeFullLength() { return this.cutLength + (this.blockDetail ? this.blockDetail?.currentSizeExpand?.length || 0 : 0) } /** 坐标偏移情况 */ placeOffX = 0 placeOffY = 0 /** 原始排版坐标 */ placeOrgX() { return this.placeX - this.placeOffX } placeOrgY() { return this.placeY - this.placeOffY } /** 反面开料 */ isTurnOver(): boolean { return this.placeStyle > 3 } /** 后转180 */ isTurnBack(): boolean { return ( this.placeStyle == PlaceStyle.BACK_TURN_BACK || this.placeStyle == PlaceStyle.FRONT_TURN_BACK ) } /** 反纹开料 */ isTurnDown(): boolean { return this.placeStyle % 2 == 1 } /** 自动排版 */ isAutoPlaced = true /** 超出板外 */ isOutBoard = false /** 已重叠 */ isOverlap = false /** 高方向 */ placeDirection = '→' /** 长边方向 */ placeDirection_Length = '→' // 开料情况 // isUseSameKnifeToHelpCut() { return this.blockDetail ? this.blockDetail.isHelpCut : false; }; /** 是否排钻 IsDoHoling */ isDrilling = true /** 是否造型 IsDoModeling */ isModeling = true /** 超限板标识 : -1=不是; 0=不判断 1=是 */ overBlockFlag = 0 /** 开料时需翻面 IsDoOtherFace */ isCutOtherFace = false /** 开料反面要处理 NeedTurnFaceToDo */ isCutTurnOver = false /** 开料面孔数 HoleCount_DoFaceA */ holeCountFaceA(): number { return this.holeListFaceA.length } /** 开料反面孔数 HoleCount_DoFaceB */ holeCountFaceB(): number { return this.holeListFaceB.length } /** 开料左侧孔数 HoleCount_DoLeft */ holeCountSideLeft = 0 /** 开料右侧孔数 HoleCount_DoRight */ holeCountSideRight = 0 /** 开料上侧孔数 HoleCount_DoUpper */ holeCountSideTop = 0 /** 开料下侧孔数 HoleCount_DoUnder */ holeCountSideBottom = 0 /** 开料面造型数 ModelCount_DoFaceA */ modelCountFaceA(): number { return this.modelListFaceA.length } /** 开料反面造型数 ModelCount_DoFaceB */ modelCountFaceB(): number { return this.modelListFaceB.length } // 不显示 /** 开料面孔 Holes_DoFaceA */ holeListFaceA: BlockHole[] = [] // 不显示 /** 开料反面孔 Holes_DoFaceB */ holeListFaceB: BlockHole[] = [] // 不显示 /** 开料面造型 Models_DoFaceA */ modelListFaceA: BlockModel[] = [] // 不显示 /** 开料反面造型 Models_DoFaceB */ modelListFaceB: BlockModel[] = [] /** 贴标位置x NotePosX */ labelPosX = 0 /** 贴标位置y NotePosY */ labelPosY = 0 // CNC高级对接-------------------------------------------------------- /** CNC正面条码 CNC_NoteA */ isCncLabelA = false /** CNC反面条码 CNC_NoteB */ isCncLabelB = false /** CNC翻面条码 CNC_NoteT */ isCncLabelTurnOver = false /** 类型 */ type = '' /** 加工组 */ processGroupName = '' /** 开门类型 */ openDoorType = OpenDoorType.NONE // 无 /** 自增小板的id接口获取 */ _blockId = '' constructor(data: any = null) { if (data != null) { for (const key in data) { if (Reflect.has(this, key)) { if (['goodsId'].includes(key)) { this[key] = data[key].toString() } else if (['width', 'length', 'thickness', 'sealLeft', 'sealRight', 'sealTop', 'sealBottom'].includes(key)) { this[key] = StringFormat.toFixed(data[key], 3) } else if (key == 'texture') { this.texture = data.texture } else if (key == 'placeHole') { this.placeHole = data.placeHole } else if (key == 'remarkJson') { let remarkList = JSON.parse(data.remarkJson == null || data.remarkJson == '' ? '[]' : data.remarkJson) this.remark1 = remarkList[0] == null ? '' : remarkList[0] this.remark2 = remarkList[1] == null ? '' : remarkList[1] this.remark3 = remarkList[2] == null ? '' : remarkList[2] this.remark4 = remarkList[3] == null ? '' : remarkList[3] this.remark5 = remarkList[4] == null ? '' : remarkList[4] } else { try { if (Object.getOwnPropertyDescriptor(this, key)?.writable == true) { this[key] = data[key] } } catch (error) { console.log(error) } } } else { // console.log('PlaceBlock Init', key) } } this.cutWidth = this.width - this.sealLeft - this.sealRight this.cutLength = this.length - this.sealTop - this.sealBottom this.cutArea = this.cutWidth * this.cutLength * 0.000001 this._blockId = data.blockId } } getRemark(rname, st = '', ed = '') { if (!this.extraRemark) return '' if (!this.extraRemark[rname]) return '' let text: string = this.extraRemark[rname] if (st != '') { let index = text.indexOf(st) if (index > -1) { // text = text.substr(index + st.length, 99999); text = text.substring(index + st.length, 99999) } } if (ed != '') { let index = text.indexOf(ed) if (index > -1) { text = text.substring(0, index) } } return text } } /** 小板明细(异形,造型,孔) */ export class PlaceBlockDetail { // 数据库定义列 /** 用户ID */ organId: number = 0 /** 数据类型 */ dataType: number = 0 /** 订单号 */ orderId: number = 0 /** 小板ID */ blockId: number = 0 /** 原柜体编号rawBoxNo */ rawBoxNo: number = 0 /** 异形定义明细 */ pointDetail: any = [] /** 造型定义明细 */ modelDetail: any = [] /** 排钻定义明细 */ holeDetail: any = [] /** 封边偏移值x */ offsetX = 0 /** 封边偏移值y */ offsetY = 0 /** 开料宽度 KaiLiaoWidth */ cutWidth = 0 /** 开料长度 KaiLiaoLength */ cutLength = 0 /** 异形点阵 */ points: BlockPoint[] = [] /** 异形点阵含封边 */ orgPoints: BlockPoint[] = [] /** 原轮廓数据 */ orgContourData = null /** 排钻 */ holes: BlockHole[] = [] /** 正面孔列表(不包含通孔和孔深大于板厚) Holes_FaceA */ holeListFaceA: BlockHole[] = [] /** 反面孔列表(不包含通孔和孔深大于板厚) Holes_FaceB */ holeListFaceB: BlockHole[] = [] /** 穿孔列表(通孔和孔深大于板厚) Holes_Through */ holeListThrough: BlockHole[] = [] /** 侧孔列表 Holes_FaceSide */ holeListSide: SideHole[] = [] /** 造型点阵 */ models: BlockModel[] = [] /** 正面造型列表(不包含打穿) Models_FaceA */ modelListFaceA: BlockModel[] = [] /** 反面造型列表(不包含打穿) Models_FaceB */ modelListFaceB: BlockModel[] = [] /** 打穿造型列表 Models_Through */ modelListThrough: BlockModel[] = [] /** 侧面造型 BlockModel SideModels 20241111 改为 BlockModel */ modelListSide: SideModel[] = [] // /** 切割板宽 */ // cuttingWidth = 0; // /** 切割板厚 */ // cuttingLength = 0; /** 板厚 */ thickness = 18 /** 是否异形 */ isUnRegular = false /** 正面有打孔 */ bigHoleInFaceA = false /** 正面孔数 */ holeCountFront = 0 /** 反面孔数 */ holeCountBack = 0 /** 穿孔数 */ holeCountThrough = 0 /** 侧孔数 */ holeCountSide = 0 /** 左侧孔数 */ holeCountLeft = 0 /** 右侧孔数 */ holeCountRight = 0 /** 上侧孔数 */ holeCountTop = 0 /** 下侧孔数 */ holeCountBottom = 0 /** 斜孔数量 */ holeCountBevelled = 0 /** 正面造型数 */ modelCountFront = 0 /** 反面造型数 */ modelCountBack = 0 /** 打穿造型数 */ modelCountThrough = 0 /** 侧面造型数量 */ modelCountSide(): number { return this.modelListSide.length } /** 下侧造型数量 */ modelCountBottom(): number { return this.modelListSide.filter(sideModel => sideModel.face == 0).length } /** 右侧造型数量 */ modelCountRight(): number { return this.modelListSide.filter(sideModel => sideModel.face == 1).length } /** 下侧造型数量 */ modelCountTop(): number { return this.modelListSide.filter(sideModel => sideModel.face == 2).length } /** 下侧造型数量 */ modelCountLeft(): number { return this.modelListSide.filter(sideModel => sideModel.face == 3).length } /** 是否有挖穿的造型 */ hasModelThrogh = false /** 双面处理 Do2Face */ isTwoFaceProcess = false // isTwoFaceProcess(): boolean // { // return this.blockDetail && this.blockDetail.isTwoFaceProcess // } // 为了缺角空间 放在右边 /** 当需要正面正纹的,最佳放置方式: 正面或正面后转 Ps00 */ placeStyleFront = PlaceStyle.FRONT // 正面 /** 正面反纹放置方式 Ps01 */ placeStyleFrontReverse = PlaceStyle.FRONT_TURN_RIGHT // 正面右转 /** 反面正纹放置方式 Ps10 */ placeStyleBack = PlaceStyle.BACK // 反面 /** 反面反纹放置方式 Ps11 */ placeStyleBackReverse = PlaceStyle.BACK_TURN_LEFT // 反面左转 /** 开料序号贴标位置x */ labelPosX = -1 /** 开料序号贴标位置y */ labelPosY = -1 /** 是否初始化 */ isInited = false /** 是否已检查 */ isChecked = false /** 全部二维刀路径集合 { model, modelID, lineID, isFaceB, name, value, knife, knifeRadius, depth, points, offset} */ // vKnifeModels: any[]; /** 是否偏移倒角 IsOffsetRounding */ isOffsetRounding = false /** 偏移值刀半径 CutR */ offsetKnifeRadius = 0 /** 当前的预铣值 preCutValue */ preMillingSize = 0 /** 该板需要辅助开料 isNeedHelpCut */ isUseSameKnifeToHelpCut = false /** 同刀辅助值 */ useSameKnifeToHelpCutGap = 2 /** 预铣外扩尺寸 preCutSizeOutOff */ preMillingExpandSize: SizeExpand | null = null /** 板外造型外扩尺寸 modelKnifeOutOff */ modelExpandSize: SizeExpand | null = null /** 2V刀路V外扩尺寸 */ vKnifeModelExpandSize: SizeExpand | null = null /** 同刀辅助外扩尺寸 sameKnfieHelpOutOff */ sameKnfieHelpExpandSize: SizeExpand | null = null /** 当前外扩 currentOutOff */ currentSizeExpand: SizeExpand | null = null /** 边框轮廓,走刀路径等(包含偏移后的轮廓结合) borderUnit */ borderContour: PlaceBorderContour | null = null // 板件扩展尺寸 数据集 plateExtraRemark: any /** 优化前的配置及其轮廓等用于恢复 */ savedSetting /** 备注 数据集 */ remarkParams: any constructor(data: any = null, sourceType: number = 2) { if (data != null) { this.remarkParams = data.remarkParams this.orderId = data.orderId this.dataType = data.dataType this.orderId = data.orderId this.blockId = data.blockId this.rawBoxNo = data.rawBoxNo // 封边偏移值 this.offsetX = data.offSet && data.offSet.x ? StringFormat.toFixed(data.offSet.x, 3) : 0 this.offsetY = data.offSet && data.offSet.y ? StringFormat.toFixed(data.offSet.y, 3) : 0 // 开料长宽(不含封边) this.cutWidth = data.cutSize ? StringFormat.toFixed(data.cutSize.width, 3) : 0 this.cutLength = data.cutSize ? StringFormat.toFixed(data.cutSize.height, 3) : 0 // 初始化 异形点阵 data.pointDetail.forEach((p) => { this.points.push(new BlockPoint(p)) }) // 初始化 异形点阵 含封边 if (!data.orgPointDetail) { data.orgPointDetail = [] } data.orgPointDetail.forEach((p) => { this.orgPoints.push(new BlockPoint(p)) }) if (!data.holes) { data.holes = data.holeDetail || [] } // 初始化 排钻列表 data.holes.forEach((h) => { this.holes.push(new BlockHole(h)) }) // 初始化 侧孔列表 if (!data.holeListSide) { data.holeListSide = data.sideHoleDetail || [] } data.holeListSide.forEach((sh) => { this.holeListSide.push(new SideHole(sh)) }) // 初始化 造型列表 data.modelDetail.forEach((t) => { this.models.push(new BlockModel(t)) }) // 初始化 侧面造型列表 if (!data.modelListSide) { data.modelListSide = [] } this.plateExtraRemark = data.plateExtraRemark data.modelListSide.forEach((t) => { this.modelListSide.push(new SideModel(t)) }) // 侧面 this.holeListFaceA = this.holes.filter(t => t.face == FaceType.FRONT) // 正面 this.holeListFaceB = this.holes.filter(t => t.face == FaceType.BACK) // 反面 this.holeListThrough = [] this.modelListFaceA = this.models.filter(t => t.face == FaceType.FRONT && (t.depth < this.thickness || t.isVKnifeModel())) this.modelListFaceB = this.models.filter(t => t.face == FaceType.BACK && (t.depth < this.thickness || t.isVKnifeModel())) this.modelListThrough = this.models.filter(t => t.depth > this.thickness - 0.01 && t.isVKnifeModel() == false) this.holeCountFront = this.holeListFaceA.length this.holeCountBack = this.holeListFaceB.length this.holeCountThrough = this.holeListThrough.length this.holeCountSide = this.holeListSide.length this.modelCountFront = this.modelListFaceA.length this.modelCountBack = this.modelListFaceB.length this.modelCountThrough = this.modelListThrough.length this.hasModelThrogh = this.modelListThrough.length > 0 this.bigHoleInFaceA = this.holeListFaceA.some(t => t.holeType == HoleType.BIG_HOLE) // 大孔 } this.isUnRegular = this.points.length > 0 } /** 保存 开料配置 */ saveSetting() { this.savedSetting = {} this.savedSetting.offsetKnifeRadius = this.offsetKnifeRadius this.savedSetting.preMillingSize = this.preMillingSize this.savedSetting.isUseSameKnifeToHelpCut = this.isUseSameKnifeToHelpCut this.savedSetting.useSameKnifeToHelpCutGap = this.useSameKnifeToHelpCutGap // SizeExpand this.savedSetting.preMillingExpandSize = this.preMillingExpandSize this.savedSetting.modelExpandSize = this.modelExpandSize this.savedSetting.vKnifeModelExpandSize = this.vKnifeModelExpandSize this.savedSetting.sameKnfieHelpExpandSize = this.sameKnfieHelpExpandSize this.savedSetting.currentExpandSize = this.currentSizeExpand // 轮廓,铣刀路径 if (this.borderContour != null) { this.savedSetting.borderContour = this.borderContour.clone() } } loadSetting() { if (!this.savedSetting) return this.offsetKnifeRadius = this.savedSetting.offsetKnifeRadius this.preMillingSize = this.savedSetting.preMillingSize this.isUseSameKnifeToHelpCut = this.savedSetting.isUseSameKnifeToHelpCut this.useSameKnifeToHelpCutGap = this.savedSetting.useSameKnifeToHelpCutGap // SizeOutOff this.preMillingExpandSize = this.savedSetting.preMillingExpandSize this.modelExpandSize = this.savedSetting.modelExpandSize this.vKnifeModelExpandSize = this.savedSetting.vKnifeModelExpandSize this.sameKnfieHelpExpandSize = this.savedSetting.sameKnfieHelpExpandSize this.currentSizeExpand = this.savedSetting.currentSizeExpand // 轮廓,铣刀路径 this.borderContour = this.savedSetting.borderContour } } /** 开门类型(0无 1左 2右 3上 4下) */ export enum OpenDoorType { /** 无 */ NONE = 0, /** 左 */ LEFT = 1, /** 右 */ RIGHT = 2, /** 上 */ TOP = 3, /** 下 */ BOTTOM = 4, } /** 纹理类型 */ export enum TextureType { /** 正纹 */ NORMAL_TEXTURE = 0, /** 可翻转 */ ROTATABLE_TEXTURE = 1, /** 反纹 */ REVERSE_TEXTURE = 2, } /** 排钻 */ export class BlockHole { /** 孔类别 */ holeType: HoleType = 0 /** 面 */ face: FaceType = 0 /** 侧孔所在面 */ sideFace: FaceType = FaceType.FRONT // 正面 /** 坐标x */ pointX: number = 0 /** 坐标y */ pointY: number = 0 /** 坐标z */ pointZ: number = 0 /** 半径 */ radius: number = 5 /** 深度 */ depth: number = 12 /** 终点坐标 */ endPoint: string = '' /** 角度 */ angle: number = 0 /** CNC不能加工 cncUndo */ isCncCanNotProcess: boolean = false /** 不能加工类型 unDoType */ cncCanNotProcessType = '' /** 是否在开料机上处理 IsDo */ isCutting: boolean = true knife: Knife | null = null constructor(data: any = null) { if (data != null) { this.holeType = data.holeType this.face = data.face this.pointX = StringFormat.toFixed(data.pointX, 3) this.pointY = StringFormat.toFixed(data.pointY, 3) this.pointZ = StringFormat.toFixed(data.pointZ, 3) this.radius = StringFormat.toFixed(data.radius, 3) this.depth = StringFormat.toFixed(data.depth, 3) this.angle = data.angle ? data.angle : 0 this.endPoint = data.endPoint } } ToSideHole(block: PlaceBlock): SideHole { let newH = new SideHole() newH.holeType = this.holeType newH.faceId = 0 newH.sideFace = SideFaceType.BOTTOM // 下侧面 newH.pointX = this.pointX newH.pointY = this.pointY newH.pointZ = this.pointZ newH.radius = 4 let diameter = this.radius * 2 if (Math.abs(diameter - 8.3) < 0.1 || Math.abs(diameter - 6.3) < 0.1 || Math.abs(diameter - 11.5) < 0.1 || Math.abs(diameter - 12) < 0.1) { newH.radius = this.radius } newH.depth = this.depth let cells = this.endPoint.split(',') if (cells.length >= 3) { // 起点坐标 let bx = Number.parseFloat(cells[0]) let by = Number.parseFloat(cells[1]) // x 相等 , 侧孔方向 上下 if (Math.abs(bx - this.pointX) < 0.1) { let toUpper = this.isToTop(block, by) if (toUpper) // y+ 向上 { newH.pointX2 = bx newH.pointY2 = this.pointY + this.depth newH.direct = 0 newH.faceId = 0 newH.sideFace = SideFaceType.BOTTOM_SIDE // 下侧面 } // y- 向下 else { newH.pointX2 = bx newH.pointY2 = this.pointY - this.depth newH.direct = 2 newH.faceId = 2 newH.sideFace = SideFaceType.TOP_SIDE // 上侧面 } } else if (Math.abs(by - this.pointY) < 0.1) { let toRight = this.isToRight(block, bx) // y相等, 侧孔方向左右 if (toRight) { // x+ 向右 newH.pointX2 = this.pointX + this.depth newH.pointY2 = by newH.direct = 3 newH.faceId = 3 newH.sideFace = SideFaceType.LEFT_SIDE // 左侧面 } // x- 向左 else { newH.pointX2 = this.pointX - this.depth newH.pointY2 = by newH.direct = 1 newH.faceId = 1 newH.sideFace = SideFaceType.RIGHT_SIDE // 右侧面 } } // x ,y 都不相等 else { newH.pointX2 = bx newH.pointY2 = by newH.direct = -1 newH.faceId = 4 newH.sideFace = SideFaceType.SPECIAL_SHAPED_SIDE // 异形侧面 } } return newH } /** 向右(bx: 起点坐标X) */ private isToRight(block: PlaceBlock, bx: number): boolean { // 在左侧外 if (bx < 0) return true // 在板内 靠左侧 if (bx > 22 && bx < 40) return true // 在右侧外 if (bx > block.width) return false // 在右侧外 if (bx > block.width - 40 && bx < block.width - 22) return false for (let i = 0; i < block.points.length; i++) { let j = i + 1 if (j == block.points.length) j = 0 let p1 = block.points[i] let p2 = block.points[j] if (Math.abs(p1.pointX - this.pointX) < 3 && Math.abs(p2.pointX - this.pointX) < 3 && (p1.pointY > this.pointY != p2.pointY > this.pointY)) { return p1.pointY > p2.pointY } } return false } /** 向上(起点坐标Y) */ private isToTop(block: PlaceBlock, by: number): boolean { // 在下侧外 if (by < 0) return true // 靠近下侧 if (by > 22 && by < 40) return true if (by > block.length) return false if (by > block.length - 40 && by < block.length - 20) return false for (let i = 0; i < block.points.length; i++) { let j = i + 1 if (j == block.points.length) j = 0 let p1 = block.points[i] let p2 = block.points[j] if (Math.abs(p1.pointY - this.pointY) < 3 && Math.abs(p2.pointY - this.pointY) < 3 && (p1.pointX > this.pointX != p2.pointX > this.pointX)) { return p1.pointX < p2.pointX } } return false } } /** 异形点 */ export class BlockPoint { /** 坐标x */ pointX: number = 0 /** 坐标y */ pointY: number = 0 /** 凹凸度 */ curve: number = 0 /** 半径 */ radius: number = 0 /** 封边 */ sealSize: number = 0 /** 是否这条边需预洗 */ isPreCutRequired = false constructor(data: any = null) { if (data != null) { let x = data.PointX != undefined ? data.PointX : data.pointX let y = data.PointY != undefined ? data.PointY : data.pointY let curve = data.Curve != undefined ? data.Curve : data.curve let radius = 1 / curve this.pointX = StringFormat.toFixed(x) this.pointY = StringFormat.toFixed(y) this.curve = curve this.radius = StringFormat.toFixed(Math.abs(radius)) if (Math.abs(this.curve) < 1e-5) { this.curve = 0 this.radius = 0 } this.sealSize = data.SealSize != undefined ? data.SealSize : data.sealSize || 0 } } copy(): BlockPoint { let nw = new BlockPoint() nw.pointX = this.pointX nw.pointY = this.pointY nw.curve = this.curve nw.radius = this.radius nw.sealSize = this.sealSize return nw } } /** 侧孔 */ export class SideHole { /** 孔类别 */ holeType: HoleType = 0 /** 面 */ faceId: number = 0 /** 侧孔所在面 */ sideFace: SideFaceType = SideFaceType.BOTTOM // 正面 /** 方向 0向上 1向左 2向下 3向右 -1斜 */ direct: number = 0 /** 坐标x */ pointX: number = 0 /** 坐标y */ pointY: number = 0 /** 坐标z */ pointZ: number = 0 /** 半径 */ radius: number = 5 /** 深度 */ depth: number = 12 /** 坐标x */ pointX2: number = 0 /** 坐标y */ pointY2: number = 0 // cncUndo: boolean = true; //cnc不能做. /** CNC不能处理 */ isCncCanNotProcess: boolean = true /** 是否可处理 IsDo */ isProcess: boolean = true knife: Knife | null = null constructor(data: any = null) { if (data != null) { this.holeType = data.holeType this.faceId = data.face this.sideFace = data.sideFace this.direct = data.sideFace this.pointX = StringFormat.toFixed(data.pointX, 3) this.pointY = StringFormat.toFixed(data.pointY, 3) this.pointZ = StringFormat.toFixed(data.pointZ, 3) this.radius = StringFormat.toFixed(data.radius, 3) this.depth = StringFormat.toFixed(data.depth, 3) this.pointX2 = StringFormat.toFixed(data.pointX2, 3) this.pointY2 = StringFormat.toFixed(data.pointY2, 3) } } } /** 孔类型 */ export enum HoleType { /** 大孔 */ BIG_HOLE = 0, /** 小孔 */ TINY_HOLE = 10, /** 木削 */ WOOD_DUST = 20, /** 木削大孔 */ WOOD_DUST_BIG_HOLE = 21, /** 层板钉 */ LAMINATED_NAIL = 30, /** 通孔 */ THROUGH_HOLE = 40, /** 造型孔 */ MODELING_HOLE = -10, /** 连接杆 */ CONNECTING_ROD = 50, } /** 板件造型 */ export class BlockModel { /** 订单号 */ orderId: string = '' /** 小板号 */ blockId: number = 0 /** 造型Id */ modelId: number = 0 /**线ID */ lineId: number = 0; /** 纹路Id */ textureId: number = 0 /** 板面 */ face: FaceType = FaceType.UNSET /** 刀号 */ knifeName: string = '' /** 刀半径 */ knifeRadius: number = 0 /** 深度 */ depth: number = 0 /** 是否可以挖空后排版 */ canSpace = false /** 是否是矩形 */ isRect = false /** 是否倾斜 至少有一条边是斜的 */ isTilt = false type = '' knife: Knife | null | undefined = null /** 有轮廓 */ hasContour() { let val = false try { if (this.originModeling != null && this.originModeling.outline != 0 && this.originModeling?.outline.map(e => e?.pts).length > 0) { val = true } } catch (error) { console.log('handle hasContour error',error) } return val // this.originModeling?.outline.map(e=>e?.pts).length >0 //this.originModeling?.outline?.pts?.length > 0 } modelWidth: any = 0 modelLength: any = 0 modelStartPoint: any = null modelEndPoint: any = null /** * 造型轮廓(孔转的造型,没有造型轮廓) * OriginModeling.outline.pts.x | y ; outline.buls */ originModeling: any = null /** 点列表 */ pointList: BlockModelPoint[] = [] /** 实际替代刀直径 */ realKnifeRadius = 0 /** 实际替代刀点阵 */ realPointList: BlockModelPoint[] = [] /** 实际刀编号 */ realKnifeId = -1 /** cnc不能加工 cncUndo */ isCncCanNotProcess: boolean = true /** 超限类型(cnc为何不能加工) unDoType */ cncCanNotProcessType = '' /** 是否在开料机加工 IsDo */ isCutting: boolean = true /** 二维造型的偏移数组 */ offsetList: ModelOffsetData[] = [] /** 转换过的二维刀路路径{isFaceB, name刀名称, offset偏移, knife刀, knifeId刀Id, knifeRadius刀半径, depth深度, points{x,y,z,bul,r}, orgOffset(源偏移)} */ VLines :any[] = [] offsetInfo = '' /** 是否二维造型 */ isVKnifeModel(): boolean { return this.offsetList.length > 0 } /** 是否三维造型 */ is3VModel(): boolean { return this.offsetList.length == 0 && this.pointList.some(t => Math.abs(t.depth - this.depth) > 0.01) } constructor(data: any = null) { if (data != null) { this.modelId = data.modelId this.lineId = data.lineId this.textureId = data.textureId this.face = data.face this.knifeName = data.knifeName ? data.knifeName.trim() : '' this.knifeRadius = StringFormat.toFixed(data.knifeRadius, 3) this.depth = StringFormat.toFixed(data.depth, 3) if (data.modelPoint) data.modelPoint.forEach(pt => { this.pointList.push(new BlockModelPoint(pt)) }) if (data.modelOffSet) data.modelOffSet.forEach(os => this.offsetList.push(new ModelOffsetData(os))) if (this.offsetList.length > 0) { let names: any = [] for (let os of this.offsetList) { if (os.name == this.knifeName) continue if (names.includes(os.name)) continue names.push(name) } if (names.length == 0) this.offsetInfo = `${this.offsetList.length - 1}` else this.offsetInfo = `${this.offsetList.length - 1}(${names.join(' ')})` } if (data.originModeling) { this.originModeling = JSON.parse(JSON.stringify(data.originModeling)) // 计算造型 // this.countModelWidthAndLength(this) } } } } /** 造型点 */ export class BlockModelPoint { /** 坐标X */ pointX: number = 2 /** 坐标Y */ pointY: number = 2 /** 半径 */ radius: number = 0 /** 深度 */ depth: number = 6 /** 凹凸度 */ curve: number = 0 constructor(data: any = null) { if (data != null) { this.pointX = StringFormat.toFixed(data.PointX || data.pointX) this.pointY = StringFormat.toFixed(data.PointY || data.pointY) this.radius = StringFormat.toFixed(Math.abs(data.Radius || data.radius)) this.depth = StringFormat.toFixed(data.Depth || data.depth) this.curve = data.Curve || data.curve } } copy(): BlockModelPoint { let obj = new BlockModelPoint() obj.pointX = this.pointX obj.pointY = this.pointY obj.radius = this.radius obj.depth = this.depth obj.curve = this.curve return obj } } /** 二维造型的偏移数据 */ export class ModelOffsetData { /** 刀名称 */ name: string = '' /** 偏移 */ offset: number = 0 /** 刀半径 */ radius: number = 0 /** 深度 */ depth: number = 0 /** 角度 */ angle: number = 0 /** 板面类型 */ face: FaceType = FaceType.UNSET fullName() { return `偏移${this.offset} 深${this.depth} 刀${this.name}` } constructor(data: any = null) { if (data != null) { let off = 0 if (data.offset != undefined) { off = data.offset } else if (data.value != undefined) { off = data.value } else if (data.value != undefined) { off = data.value } this.name = data.Name != undefined ? data.Name : data.name this.offset = StringFormat.toFixed(data.offset || data.value || data.value) this.radius = StringFormat.toFixed(data.Radius || data.radius) this.depth = StringFormat.toFixed(data.Deep || data.depth) this.face = data.Face != undefined ? data.Face : data.face this.angle = StringFormat.toFixed(data.Angle || data.angle) } } } /** * 侧面造型 所在的面 0 下 1 右 2上 3 左 其它待测试 */ export enum SideFaceType { /** 下 */ BOTTOM = 0, /** 右 */ RIGHT = 1, /** 上 */ TOP = 2, /** 左 */ LEFT = 3, /** 左侧面 */ LEFT_SIDE = 21, /** 右侧面 */ RIGHT_SIDE = 22, /** 上侧面 */ TOP_SIDE = 23, /** 下侧面 */ BOTTOM_SIDE = 24, /** 弧形侧面 */ CURVED_SIDE = 29, /** 异形侧面 */ SPECIAL_SHAPED_SIDE = 30, } /** 侧边造型 * * 侧面造型的点阵判断逻辑 * * 提要: * 1、 face 为 该造型在该板件的第几条边上 * 2、 originModeling 内的造型轮廓点阵的 X Y轴 为 : * 以该造型为正面 且小板板面朝上 造型为正面的左下角为原点 板厚 为 Y 横象为X * 注:最终使用的时候 要得到该造型 对应机台的 轮廓数据和刀路数据 * * 平行判断 参考 checkIsTilt 修改一个新的方法 * 是否在板内 可使用 isPointInBlock * * 要求:要得到 * * 转换逻辑 * 1、通过face 获取 该造型所在的边 * 2、将这条边 与 板件的坐标轴做比较 判断平行 * 情况1:与板件的X轴 平行 则造型 可能为 上 || 下 ,使用 isPointInBlock 判断 具体是上 还是下 * 情况2:与板件的Y轴 平行 则造型 可能为 左 || 右 , 使用 isPointInBlock 判断 具体是左 还是右 * 情况3:都不平行 则 朝向的值为斜边 * 最终得到造型的朝向 * 3、依据边的坐标和造型的朝向 可以 根据造型的轮廓数据转为 对应机台的轮廓数据 和刀路数据 */ export class SideModel { /** 订单号 */ orderId: string = '' /** 小板号 */ blockId: number = 0 /** 造型Id */ modelId: number = 0 /**线ID */ lineId: number = 0; /** 纹路Id */ textureId: number = 0 /** 板面 造型所在的边 第几条边 */ face: SideFaceType = 0 /** 刀号 */ knifeName: string = '' /** 刀半径 */ knifeRadius: number = 0 /** 深度 */ depth: number = 0 /** 是否可以挖空后排版 */ canSpace = false /** 是否是矩形 */ isRect = false /** 是否倾斜 至少有一条边是斜的 */ isTilt = false /** 暂时没用 */ type = '' /** 造型方向 -2 未知(是异常情况 要排查) -1 斜的 0 下 1右 2上 3左 10 左下斜 11 右下斜 12 右上斜 13 左上斜 */ direction = 0 knife: Knife | null = null /** 有轮廓 */ hasContour() { return this.originModeling != null && this.originModeling.outline != 0 && this.originModeling?.outline?.pts?.length > 0 } /** 侧面造型 宽 */ modelWidth: any = 0 /** 侧面造型 长 */ modelLength: any = 0 /** 侧面造型 起点 */ modelStartPoint: any = null /** 侧面造型 终点 */ modelEndPoint: any = null /** * 造型轮廓(孔转的造型,没有造型轮廓) * OriginModeling.outline.pts.x | y ; outline.buls */ originModeling: any = null /** 点列表 */ pointList: BlockSideModelPoint[] = [] /** 实际替代刀直径 */ realKnifeRadius = 0 /** 实际替代刀点阵 */ realPointList: BlockSideModelPoint[] = [] /** 实际刀编号 */ realKnifeId = -1 /** cnc不能加工 cncUndo */ isCncCanNotProcess: boolean = true /** 超限类型(cnc为何不能加工) unDoType */ cncCanNotProcessType = '' /** 是否在开料机加工 IsDo */ isCutting: boolean = true /** 二维造型的偏移数组 */ offsetList: ModelOffsetData[] = [] /** 转换过的二维刀路路径{isFaceB, name刀名称, offset偏移, knife刀, knifeId刀Id, knifeRadius刀半径, depth深度, points{x,y,z,bul,r}, orgOffset(源偏移)} */ VLines = [] offsetInfo = '' /** 是否二维造型 */ isVKnifeModel(): boolean { return this.offsetList.length > 0 } /** 是否三维造型 */ is3VModel(): boolean { return this.offsetList.length == 0 && this.pointList.some(t => Math.abs(t.depth - this.depth) > 0.01) } constructor(data: any = null) { if (data != null) { this.modelId = data.modelId this.lineId = data.lineId this.textureId = data.textureId this.face = data.face this.knifeName = data.knifeName ? data.knifeName.trim() : '' this.knifeRadius = StringFormat.toFixed(data.knifeRadius, 3) this.depth = StringFormat.toFixed(data.depth, 3) // if (data.originModeling) // { // this.originModeling = JSON.parse(JSON.stringify(data.originModeling)) // MachineHelper.countModelWidthAndLength(this) // } } } } /** 小板区域 */ export enum BlockRegion { /** 左下 = 0 */ LEFT_BOTTOM = 0, /** 右下 = 1 */ RIGHT_BOTTOM = 1, /** 右上 = 2 */ RIGHT_TOP = 2, /** 左上 = 3 */ LEFT_TOP = 3, } /** 造型偏移 */ export class SizeExpand { /** 左 */ left: number = 0 /** 右 */ right: number = 0 /** 上 */ top: number = 0 /** 下 */ bottom: number = 0 /** 板外扩宽 */ width: number = 0 /** 板外扩长 */ length: number = 0 /** 排版外扩宽 */ outWidth: boolean /** 排版外扩长 */ outLength: boolean /** 是否完成 */ hasDone: boolean constructor(data: any = null) { if (data != null) { this.left = data.left || 0 this.right = data.right || 0 this.bottom = data.bottom || 0 this.top = data.top || 0 this.width = (this.left + this.right) || 0 this.length = (this.top + this.bottom) || 0 } } /** 设置长宽 */ setSize() { this.width = this.left + this.right this.length = this.top + this.bottom } toString() { return `左:${this.left.toFixed(2)} 右:${this.right.toFixed(2)} 上:${this.top.toFixed(2)} 下:${this.bottom.toFixed(2)}` } } /** * 板件侧面早些点阵 */ export class BlockSideModelPoint { /** 坐标X */ pointX: number = 2 /** 坐标Y */ pointY: number = 2 /** 坐标Z */ pointZ: number = 2 /** 半径 */ radius: number = 0 /** 深度 */ depth: number = 6 /** 凹凸度 */ curve: number = 0 constructor(data: any = null) { if (data != null) { this.pointX = StringFormat.toFixed(data.pointX || data.x) this.pointY = StringFormat.toFixed(data.pointY || data.y) this.pointZ = StringFormat.toFixed(data.pointZ || data.z) this.radius = StringFormat.toFixed(Math.abs(data.radius || 0)) this.depth = StringFormat.toFixed(data.depth) this.curve = data.curve || data.buls || 0 if (this.radius == 0 && this.curve != 0) { this.radius = 1 / this.curve } } } copy(): BlockSideModelPoint { let obj = new BlockSideModelPoint() obj.pointX = this.pointX obj.pointY = this.pointY obj.radius = this.radius obj.depth = this.depth obj.curve = this.curve return obj } } /** 放置板的边框集合,内部轮廓,偏移后轮廓 */ export class PlaceBorderContour { /** 放置方式 */ placeStyle: PlaceStyle = PlaceStyle.FRONT // 正面 /** 1成品轮廓 必须提前生成 */ borderFinal: CAD.Curve2d[] /** 2原始轮廓 <不含预铣> 必须提前生成 */ borderOrg: CAD.Curve2d[] /** 2.原始轮廓含预铣 border_preCut */ borderPreMilling: CAD.Curve2d[] = [] /** 2原始多段线 《不含预铣》 必须提前生成,用于 计算造型,2v板外干涉轮廓 */ polylineOrg: Polyline | null = null /** 3.1开料轮廓 <含预铣> */ border: CAD.Curve2d[] = [] /** 3.2真.开料轮廓.同刀辅助._有预铣带预铣) border_tdfz */ borderSameKnifeHelpCut: CAD.Curve2d[] = [] /** 走刀路径(预铣) */ cutLines: CAD.Curve2d[] = [] /** 走刀路径2(预铣 同刀辅助) cutLines_tdfz */ cutLinesSameKnifeHelpCut: CAD.Curve2d[] = [] /** 排版轮廓+预铣+同刀辅助+刀半径+缝隙/2 再与造型外扩并集 border_moving */ borderMoving: CAD.Curve2d[] = [] /** 优化轮廓,用于王者优化 border_wxyh */ borderKingOptimize: CAD.Curve2d[] = [] /** 板内轮廓挖穿造型(borders_inner) */ borderModelThrough: CAD.Curve2d[][] = [] /** 板内轮廓挖穿r(borders_inner_r) */ borderModelThroughR: number[] = [] /** 板内挖穿造型走刀路径,内部走刀轮廓(cutLines_inner) */ cutLinesModelThrough: CAD.Curve2d[][] = [] /** 板内排版轮廓,用于手动排版定位(borders_inner_place) */ borderInnerPlace: CAD.Curve2d[][] = [] /** 板内空间:挖穿造型(spaces_inner) */ blockInnerSpace: PlaceSpace[] = [] /** 板外空间:缺角(spaces_outer) */ blockOuterSpace: PlaceSpace[] = [] /** 空间,包括造型矩形与缺角空间 */ spaces: PlaceSpace[] = [] /** 2v刀路,板外轮廓 */ polylines2vModel: Polyline[] = [] /** 造型,板外轮廓 */ polylinesOutModel: Polyline[] = [] /** 翻转后的这些轮廓集合 */ placeContours: PlaceBorderContour[] constructor(placeStyle: PlaceStyle, borderFinal: CAD.Curve2d[], borderOrg: CAD.Curve2d[]) { this.placeStyle = placeStyle this.borderFinal = borderFinal this.borderOrg = borderOrg this.placeContours = [] } /** 开料刀 半径变化了 */ cutKnifeChanged() { this.cutLines = [] this.cutLinesSameKnifeHelpCut = [] this.borderMoving = [] // this.borderKingOptimize = null; this.borderModelThrough = [] this.borderInnerPlace = [] this.blockInnerSpace = [] this.blockOuterSpace = [] if (this.placeContours) this.placeContours.forEach(t => t.cutKnifeChanged()) } /** 预铣值变化, 将有关轮廓全部清理 */ preValueChanged() { // console.log('预铣值变化, 将有关轮廓全部清理') this.border = [] this.borderSameKnifeHelpCut = [] this.cutLines = [] this.cutLinesSameKnifeHelpCut = [] this.borderMoving = [] // this.borderKingOptimize = null; this.blockOuterSpace = [] if (this.placeContours) this.placeContours.forEach(t => t.preValueChanged()) } /** 同刀辅助 变化了 */ sameKnifeGapChanged() { this.borderSameKnifeHelpCut = [] this.cutLinesSameKnifeHelpCut = [] this.borderMoving = [] // this.borderKingOptimize = null; this.blockOuterSpace = [] if (this.placeContours) this.placeContours.forEach(t => t.sameKnifeGapChanged()) } /** 克隆 */ clone(): PlaceBorderContour { let newObj = new PlaceBorderContour(this.placeStyle, this.borderFinal, this.borderOrg) newObj.borderPreMilling = this.borderPreMilling newObj.polylineOrg = this.polylineOrg newObj.border = this.border newObj.borderSameKnifeHelpCut = this.borderSameKnifeHelpCut newObj.cutLines = this.cutLines newObj.cutLinesSameKnifeHelpCut = this.cutLinesSameKnifeHelpCut newObj.borderMoving = this.borderMoving // newObj.borderKingOptimize = this.borderKingOptimize; newObj.borderModelThrough = this.borderModelThrough newObj.borderModelThroughR = this.borderModelThroughR newObj.cutLinesModelThrough = this.cutLinesModelThrough newObj.borderInnerPlace = this.borderInnerPlace newObj.blockInnerSpace = this.blockInnerSpace newObj.blockOuterSpace = this.blockOuterSpace newObj.spaces = this.spaces newObj.polylines2vModel = this.polylines2vModel newObj.polylinesOutModel = this.polylinesOutModel newObj.placeContours = [] for (let pc of this.placeContours) { if (pc) { let npc = pc.clone() newObj.placeContours.push(npc) } } console.log('克隆', newObj) return newObj } } /** 优化空间 */ export class PlaceSpace { /** 大板ID */ boardId: number /** 空间ID */ spaceId: number /** 坐标x */ x: number /** 坐标y */ y: number /** 宽 */ width: number /** 长 */ length: number /** 是否是小板内部造型空间 IsInner */ isBlockInnerSpace = false /** 顶点Y */ topY(): number { return this.y + this.length } /** 右边X */ topX(): number { return this.x + this.width }; constructor(x: number, y: number, width: number, length: number) { this.boardId = 0 this.spaceId = 0 this.x = x this.y = y this.width = width this.length = length } /** 克隆 */ clone(): PlaceSpace { let obj = new PlaceSpace(this.x, this.y, this.width, this.length) return obj } static create(x1, y1, x2, y2): PlaceSpace { return new PlaceSpace(x1, y1, x2 - x1, y2 - y1) } } /** 开料板材 */ export class PlaceMaterial { /** 订单号(*) */ orderId = '' /** 板材ID(*) */ goodsId = '' /** 板材名称(*) */ goodsName = '' /** 规格(*) */ spec = '' /** 材质(*) */ material = '' /** 颜色(*) */ color = '' /** 品牌(*) */ brand = '' /** 有纹路 */ hasTexture = false /** 最后保存时间 */ updateTime = '' /** 纹路标识 */ get textureFlag(): string { return this.hasTexture ? '有' : '无' } /** 板材全名 */ get fullName(): string { return `${this.hasTexture ? '' : '【无纹】'}${this.thickness} ${this.goodsName} ${this.material} ${this.color}` } /** 板材原宽 */ orgWidth = 1220 /** 板材原长 */ orgLength = 2440 /** 板宽,用于生产 */ width = 1220 /** 板长 */ length = 2440 /** 板厚 */ thickness = 18 /** 全部尺寸 */ get fullSize(): string { return `${this.length}*${this.width}*${this.thickness}` } /** 修边值(*) Border */ cutBorder = 3 /** 开料刀直径(*) CutDia */ diameter = 6 /** 开料刀路间隙(*) CutGap */ cutKnifeGap = 1 /** 预铣值 PreCutValue */ preMillingSize = 0 /** 是否辅助开料 HelpCut */ isHelpCut = false /** 辅助开料标识 */ get strHelpCut() { return this.isHelpCut ? '✔' : '✘' } /** 同刀辅助开料偏移 SameKnifeHelpCutGap */ helpCutGap = 0 /** 开料刀ID */ cutKnifeId = -1 /** 开料刀名称 */ cutKnifeName = '' /** 辅助刀ID */ helpKnifeId = -1 /** 辅助刀名称 */ helpKnifeName = '' get strHelpKnifeName() { return this.isHelpCut ? this.helpKnifeName : '' } /** 是否已优化(*) isSorted */ isOptimized = false get optimizedFlag() { return this.isOptimized ? '是' : '-' } /** 大板数(*) */ boardCount = 0 /** 余料板数 */ remainBoardCount = 0 /** 最小板号(*) */ minBoardId = 0 /** 最大板号(*) */ maxBoardId = 0 /** 当前板号 */ currentBoardId = 0 /** 总平均利用率(*) AvgLyr_All */ avgUsageRateAll = 0 /** 前N块板(不包含最后一块板)的平均利用率(*) AvgLyr_NoLastOne */ avgUsageRateExcludeLastBoard = 0 /** 最后一块板的利用率(*) Lyr_LastOne */ usageRateLastBoard = 0 /** 分配到该板材的 小板数量 */ allBlockCount = 0 /**分配到该板材的优化后小板数量 -- 选择优化的板件数目 */ selectedBlockCount = 0 /** 分配到该板材的优化后 未被优化的 小板数量 */ noPlaceBlockCount = 0 /** 优化时大板数(*) */ optimizingBoardCount = 0 /** 优化时余料板数 */ optimizingRemainBoardCount = 0 /** 优化时不含余料的大板数 */ get OptimizingNoRemainBoardCount() { return this.optimizingBoardCount - this.optimizingRemainBoardCount } /** 优化时总平均利用率(*) */ optimizingAvgUsageRateAll = 0 /** 优化时前N块板(不包含最后一块板)的平均利用率(*) */ optimizingAvgUsageRateExcludeLastBoard = 0 /** 优化时最后一块板的利用率(*) */ optimizingUsageRateLastBoard = 0 /** 优化时间 */ placeTime /** 使用大板情况(*) */ usedBoardInfo = '' /** 小板排版情况(*) */ blockPlaceInfo = '' /** 余料板情况 */ remainBoardInfo = '' /** 翻面开料的大板数 BoardCount_do2Face */ boardCountFlipFace = 0 /** 小板数 */ blockCount = 0 /** 小板总面积 */ blockArea = 0 /** 封边长度 [{t:1,l:233}, {t:2,l:100}] */ edgeSealLengthList = [] edgeSealLengthStr() { let s = '' for (let rt of this.edgeSealLengthList) { s += `[${rt.t}]${rt.l}米;` } return s } /** 余料前利用(异形优化) */ // ScrapBoardList: ScrapBoard[] = []; remainBoardList: RemainBoard[] = [] /** 后余料板 */ remainList: any[] = [] /** 大板(优化)列表 */ boardList: PlaceBoard[] = [] /** 小板(优化)列表 */ blockList: PlaceBlock[] = [] /** 是否有锁定的大板 */ hasBoardLocked() { return this.boardList.some(t => t.isLocked) } /** 最优优化结果(临时) */ tempBestPlaceResult: MaterialPlaceResult | null = null tempBestPlaceResultLast: MaterialPlaceResult | null = null tempBestPlaceResultLastTime = 0 /** 需要最后一片重新计算 */ rePlaceLastBoardRequired = false tempPlaceUnregular: boolean = false /** 最优优化结果(临时)标识 */ tempPlaceResultFlag() { return (this.tempBestPlaceResult) ? '有' : '-' } /** 最优优化结果是否只使用没锁定的 */ tempPlaceResultOnyUnlockedBoard = false /** 最后优化错误信息 */ tempPlaceResultError: string = '' /** 移动小板临时仓 */ moveBlockList: PlaceBlock[] = [] /** 新优化前原配置,用于取消优化后还原到原先的配置 */ savedSetting constructor(data: any = null) { if (data != null) { this.boardList = data?.boardList || [] this.boardCount = data?.boardCount || 0 this.orderId = data.orderId this.goodsId = data.goodsId this.goodsName = data.goodsName this.spec = data.spec this.material = data.material this.color = data.color this.brand = data.brand this.hasTexture = true if (!(data.hasTexture == null || data.hasTexture == undefined)) this.hasTexture = data.hasTexture this.orgWidth = StringFormat.toFixed(Number(data.orgWidth || data.width)) this.orgLength = StringFormat.toFixed(Number(data.orgLength || data.length)) this.width = StringFormat.toFixed(Number(data.width)) this.length = StringFormat.toFixed(Number(data.length)) this.thickness = StringFormat.toFixed(Number(data.thickness)) this.cutBorder = StringFormat.toFixed(Number(data.cutBorder)) this.diameter = StringFormat.toFixed(Number(data.diameter)) this.cutKnifeGap = StringFormat.toFixed(Number(data.cutKnifeGap)) this.preMillingSize = data.preMillingSize || 0 this.isHelpCut = data.isHelpCut || false this.helpCutGap = data.helpCutGap || 0 this.cutKnifeId = data.cutKnifeId || -1 this.helpKnifeId = data.helpKnifeId || -1 this.isOptimized = Boolean(data.isOptimized) this.boardCount = StringFormat.toFixed(Number(data.boardCount)) this.remainBoardCount = StringFormat.toFixed(data.remainBoardCount ? Number(data.remainBoardCount) : 0) this.minBoardId = Number(data.minBoardId) this.maxBoardId = Number(data.maxBoardId) this.avgUsageRateAll = StringFormat.toFixed(Number(data.avgUsageRateAll)) this.avgUsageRateExcludeLastBoard = StringFormat.toFixed(Number(data.avgUsageRateExcludeLastBoard)) this.usageRateLastBoard = StringFormat.toFixed(Number(data.usageRateLastBoard)) this.usedBoardInfo = data.usedBoardInfo this.blockPlaceInfo = data.blockPlaceInfo this.remainBoardInfo = data.remainBoardInfo ? data.remainBoardInfo : '' // this.remainBoardList = data.remainBoardList ? data.remainBoardList : [] if (Array.isArray(data.remainBoardList)) { this.remainBoardList = data.remainBoardList } else { this.remainBoardList = data.remainBoardInfo ? JSON.parse(this.remainBoardInfo) : '' } this.updateTime = data['this.updateTime'] || '' } } /** 保存 原尺寸,开料刀,预铣,辅助开料 */ saveSetting() { let setting: any = {} // 尺寸, setting.orgWidth = this.orgWidth setting.orgLength = this.orgLength setting.width = this.width setting.length = this.length setting.thickness = this.thickness setting.preMillingSize = this.preMillingSize setting.isHelpCut = this.isHelpCut setting.helpCutGap = this.helpCutGap setting.diameter = this.diameter setting.cutKnifeId = this.cutKnifeId setting.cutKnifeName = this.cutKnifeName setting.helpKnifeId = this.helpKnifeId setting.helpKnifeName = this.helpKnifeName this.savedSetting = setting // 小板备份资料 let createTime = Date.now() for (let block of this.blockList) { if (block.blockDetail) { let savedObj = block.blockDetail.savedSetting if (savedObj && savedObj.createTime == createTime) break // 已备份 block.blockDetail.saveSetting() block.blockDetail.savedSetting.createTime = createTime } } } loadSetting() { if (this.savedSetting == null) return // 尺寸, this.orgWidth = this.savedSetting.orgWidth this.orgLength = this.savedSetting.orgLength this.width = this.savedSetting.width this.length = this.savedSetting.length this.thickness = this.savedSetting.thickness this.preMillingSize = this.savedSetting.preMillingSize this.isHelpCut = this.savedSetting.isHelpCut this.helpCutGap = this.savedSetting.helpCutGap this.diameter = this.savedSetting.diameter this.cutKnifeId = this.savedSetting.cutKnifeId this.cutKnifeName = this.savedSetting.cutKnifeName this.helpKnifeId = this.savedSetting.helpKnifeId this.helpKnifeName = this.savedSetting.helpKnifeName for (let block of this.blockList) { if (block.blockDetail) { block.blockDetail.loadSetting() block.blockDetail.savedSetting = null } } } } /** 排单大板 */ export class PlaceBoard { /** 数据源ID */ sourceId = 0 /** 大板编码(余料板号) */ boardNo = '' /** 大板ID */ boardId = 0 /** 大板ID(按全排单) */ fullBoardId = 0 /** 大板宽 */ width = 0 /** 大板长/高 */ length = 0 /** 面积 */ area = 0 /** 小板数 */ blockCount = 0 /** 利用面积 BlockSize */ blockArea = 0 /** 利用率 */ usageRate = 0 /** 余料板异形 IsOddmengt */ isAdnormal() { return this.points && this.points.length > 0 } /** 余料板异形点{x,y,bul} */ points: any[] = [] /** 是否加工2面, 需反面 IsDo2Face */ isTwoFaceProcessing() { let res = this.blockList.some(e => e.isDoubleFaceProcess()) return res } /** 是否锁定 */ isLocked = false /** 是否开料 */ isCuted = false /** 开料状态 * * 0 未开料 1 开料中 2 已开料 */ cutedType = 0 /** 小板列表 */ blockList: PlaceBlock[] = [] /** 余料板列表 ScrapBlockList */ remainBlockList: RemainBlock[] = [] /** 需要生成余料空间 needToScrapSpace */ isCreateRemainSpace = false /** 异形大板的轮廓线 */ polyline?: Polyline /** 无法加工的左边出现造型 */ hasModelOnLeft = false /** 无法加工的右边出现造型 */ hasModelOnRight = false /** 构造函数 */ constructor(boardId: number, width: number, length: number, sourceId = 0, boardNo = '') { this.sourceId = sourceId this.boardId = boardId this.width = width this.length = length this.boardNo = boardNo this.area = width * length * 0.000001 this.blockList = [] } reset() { this.blockCount = this.blockList.length this.blockArea = ArrayExt.sum(this.blockList, t => t.area) this.usageRate = (100 * this.blockArea) / this.area // this.isTwoFaceProcessing = this.blockList.some(t => t.isCutOtherFace) } addBlock(block: PlaceBlock) { if (this.blockList.includes(block)) return this.blockList.push(block) this.reset() } removeBlock(block: PlaceBlock) { let index = this.blockList.findIndex(t => t == block) if (index == -1) return this.blockList.splice(index, 1) this.reset() } getSize(): string { return `${this.width}*${this.length}` } } /** 实际开料的板材 || 余料板材 */ export class RemainBoard { /** 余料板ID */ id: number | string = '' /** 源排单ID */ orgPlanId: number | string = '' /** 排单ID */ planId: number | string = '' /** 状态(未使用 = 0, 已使用 = 1) */ status: number = 0 /** 商品ID */ goodsId: number | string = '' /** 商品名 */ goodsName: string = '' /** 材质 */ material: string = '' // /** 材料名 */ // materialName: string = ''; /** 颜色 */ color: string = '' /** 宽 */ width: number = 0 /** 长 */ length: number = 0 /** 品牌 */ brand: string = '' // /** 保存仓库 */ // storeHouse: string = ''; /** 纹路 */ texture?: string /** 排单号 */ planCode: string = '' /** 数量 */ count: number = 0 /** 排版宽 */ placeWidth() { return this.placeStyle % 2 == 0 ? this.width : this.length } /** 排版长 */ placeLength() { return this.placeStyle % 2 == 0 ? this.length : this.width } /** 厚度 */ thickness: number | undefined /** 轮廓 */ outLineJson: string = '{}' /** 备注 */ remark: string = '' /** */ basePolyline: Polyline | undefined /** 排版样式 */ placeStyle: PlaceStyle = PlaceStyle.FRONT /** 排版多段线 */ placePolyline: Polyline | undefined /** 是否已使用 */ isUsed: boolean = false /** 是否已入库 */ isStored = false /** 是否开料 */ isCuted = false /**是否开料 */ cutedType = 0 /** 实际优化板材的优化数据 */ // placeBoardList: BoardPlaceResult[] = [] /** 实际开料大板的数量 */ usedCount = 0 /** 总利用率 */ avgUsageRateAll = 0 /** 前N块板利用率 */ avgUsageRateExcludeLastBoard = 0 /** 最后一块板利用率 */ usageRateLastBoard = 0 copy(): RemainBoard { let obj = new RemainBoard() obj.id = this.id obj.planId = this.planId obj.status = this.status obj.goodsId = this.goodsId obj.goodsName = this.goodsName obj.material = this.material obj.color = this.color obj.width = this.width obj.length = this.length obj.thickness = this.thickness obj.outLineJson = this.outLineJson obj.remark = this.remark obj.placeStyle = this.placeStyle obj.isUsed = this.isUsed obj.texture = this.texture return obj } } /** 余料小板 */ export class RemainBlock { /** 余料板ID */ remainId: number = 0 /** 排版坐标x */ placeX: number /** 排版坐标y */ placeY: number /** 开料宽 */ placeWidth: number /** 开料长 */ placeLength: number /** 是否不规则 */ isUnRegular = false /** 是否重叠 */ isOverlap = false /** 是否已录入余料库 */ isStored = false private pointlist: any = [] points() { if (this.pointlist.length == 0) { this.pointlist.push({ x: 0, y: 0 }) this.pointlist.push({ x: this.placeWidth, y: 0 }) this.pointlist.push({ x: this.placeWidth, y: this.placeLength }) this.pointlist.push({ x: 0, y: this.placeLength }) } return this.pointlist } private pl: Polyline | null = null get polyline() { return this.pl } set polyline(v) { this.pl = v; this.polylineOffset = null } /** 多段线偏移 */ polylineOffset?: Polyline | null constructor(x, y, width, length) { this.placeX = x this.placeY = y this.placeWidth = width this.placeLength = length } /** 修改大小 */ reSize(width, length) { if (this.isUnRegular) return this.placeWidth = width this.placeLength = length this.pointlist = [] this.pl = null this.polylineOffset = null } setPoints(pts) { this.pointlist = pts if (this.pointlist.length == 0 || this.pointlist.length == 4) this.isUnRegular = false else this.isUnRegular = true this.polyline = null this.polylineOffset = null } load(data) { this.remainId = data.remainId this.placeX = data.placeX this.placeY = data.placeY this.placeWidth = data.placeWidth this.placeLength = data.placeLength this.isUnRegular = data.isUnRegular this.pointlist = data.pointlist this.isStored = data.isStored || false } } /** 板材优化结果 */ export class MaterialPlaceResult { /** 线程ID */ threadId = 0 /** 使用时间 */ usedTime = 0 /** 优化次数 */ placeCount = 0 /** 大板数 */ boardCount = 0 /** 总平均利用率 */ avgUsageRateAll = 0 /** 前N块板(不包含最后一块板)的平均利用率 */ avgUsageRateExcludeLastBoard = 0 /** 最后一块板的利用率 */ usageRateLastBoard = 0 /** 余料板数 */ remainBoardCount = 0 /** 大板列表 */ boards: BoardPlaceResult[] = [] /** 小板优化数据 */ results: BlockPlaceResult[] = [] /** 优化是否全部完成 */ placeStoped = false /** 余料板利用情况 */ remailBoardList: any[] = [] constructor() { } /** 比other 更好 */ isBetterThan(other: MaterialPlaceResult): boolean { if (this.boardCount < other.boardCount) return true if (this.usageRateLastBoard < other.usageRateLastBoard) return true return false } } export class BoardPlaceResult { /** 大板ID */ boardId = 0 /** 宽 */ width = 0 /** 长 */ length = 0 /** 是否余料板 */ isRemainBoard = false /** 余料板编码 */ remainNo = '' /** 余料板ID */ remainId = 0 /** 是否废弃物 */ isScrap = false /** 点列表 */ points: any[] = [] /** 小板排版结果 */ blocks: BlockPlaceResult[] = [] /** 小板排版 */ objects: any[] = [] /** 面积 */ area = 0 /** 是否双面加工 */ isTwoFaceProcess = false cutedType = 0 isLock = false /**当前大板的利用率 */ // avgUsageRate = 0 constructor() { } /** 是否有异形板重叠 */ hasOverLapBlock() { for (let i = 0; i < this.blocks.length; i++) { let b1 = this.blocks[i] for (let j = i + 1; j < this.blocks.length; j++) { let b2 = this.blocks[j] if (this.isOverLap(b1, b2)) return true } } return false } /** 两块板是否是否重叠 */ isOverLap(b1: BlockPlaceResult, b2: BlockPlaceResult): boolean { let l1 = { x: b1.placeX, y: b1.placeY + b1.length } let r1 = { x: b1.placeX + b1.width, y: b1.placeY } let l2 = { x: b2.placeX, y: b2.placeY + b2.length } let r2 = { x: b2.placeX + b2.width, y: b2.placeY } if (l1.x > r2.x || l2.x > r1.x) return false if (l1.y < r2.y || l2.y < r1.y) return false return true } } /** 小板优化结果 */ export class BlockPlaceResult { /** 小板号 */ blockId = 0 /** 小板编号 */ blockNo = '' /** 大板ID */ boardId: number /** 排版情况: 排版ID */ placeId: number /** 排版情况: 大板坐标X */ placeX: number // 坐标 /** 排版情况: 大板坐标Y */ placeY: number /** 宽 */ width: number /** 长 */ length: number /** 排版情况正纹 */ placeStyle: PlaceStyle /** 面积 */ area: number constructor(blockId: number, boardId: number, placeId: number, x: number, y: number, width: number, length: number, pstyle: PlaceStyle, area: number) { this.blockId = blockId this.boardId = boardId this.placeId = placeId this.placeX = x this.placeY = y this.placeStyle = pstyle this.width = width this.length = length this.area = area } }