Files
cut-abstractions/samples/confClass.ts

2762 lines
82 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

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

import { 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> | 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<Knife>
/**
* 板面类型
* 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 = <TextureType>data.texture
} else if (key == 'placeHole') {
this.placeHole = <HoleArrange>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 = <HoleType>data.holeType
this.face = <FaceType>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 = <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 = <FaceType>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 ? <FaceType>data.Face : <FaceType>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 = <SideFaceType>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
}
}