4815 lines
153 KiB
TypeScript
4815 lines
153 KiB
TypeScript
import { StringFormat } from "./StringFormat"
|
||
import type * as CAD from './common/base/CAD'
|
||
import { Polyline } from "cadapi"
|
||
import { ArrayExt } from "./ArrayExt"
|
||
import { BlockHelper } from "./common/LayoutEngine/BlockHelper"
|
||
import { BlockSizePlus } from "./common/LayoutEngine/BlockSizePlus"
|
||
import { Point } from "./common/Vector2"
|
||
|
||
|
||
/**配置项属性 */
|
||
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?.holeCountLeft || 0 }
|
||
/** 右侧孔数 HoleCount_Right */
|
||
holeCountRight() {
|
||
return this?.blockDetail?.holeCountRight || 0
|
||
}
|
||
/** 侧孔数 HoleCount_Upper */
|
||
holeCountTop() { return this?.blockDetail?.holeCountTop || 0 }
|
||
/** 侧孔数 HoleCount_Under */
|
||
holeCountBottom() { return this?.blockDetail?.holeCountBottom || 0 }
|
||
/** 正面造型数 */
|
||
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 ? this.blockDetail.currentSizeExpand : new SizeExpand() };
|
||
/** 排版宽 加上预铣等外括 ,开料刀半径 ,缝隙 */
|
||
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: any = 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 */
|
||
sameKnifeHelpExpandSize?: 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.sameKnifeHelpExpandSize = this.sameKnifeHelpExpandSize
|
||
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.sameKnifeHelpExpandSize = this.savedSetting.sameKnifeHelpExpandSize
|
||
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
|
||
blockNo?: string | number
|
||
|
||
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
|
||
|
||
blockNo?: string| number
|
||
/** 有轮廓 */
|
||
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)
|
||
val = false
|
||
}
|
||
|
||
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 = false
|
||
/** 排版外扩长 */
|
||
outLength: boolean = false
|
||
/** 是否完成 */
|
||
hasDone: boolean = false
|
||
|
||
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: any = []
|
||
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
|
||
}
|
||
}
|
||
|
||
export enum PlaceType {
|
||
/** 凸包模式 (凸包面积) */
|
||
Hull = 0,
|
||
/** 盒子模式 (长乘以宽) */
|
||
Box = 1,
|
||
/** 重力模式(重力) */
|
||
Gravity = 2,
|
||
}
|
||
|
||
export class BlockBorderPoint {
|
||
/** 板 */
|
||
block: PlaceBlock
|
||
/** 原坐标x */
|
||
x: number
|
||
/** 原坐标y */
|
||
y: number
|
||
/** 大板坐标X */
|
||
placeX: number
|
||
/** 大板坐标Y */
|
||
placeY: number
|
||
|
||
/** 拖拉点距切割后板的坐标偏移x */
|
||
bx = 0
|
||
/** 拖拉点距切割后板的坐标偏移x */
|
||
by = 0
|
||
/** 在placed线框中的序号 */
|
||
curveIndex: number
|
||
/** 在板的位置: 10:基点(左下点);1:右下角;2:右上角;3:左上角; -1:表示异形非顶点 areaID */
|
||
posId: number
|
||
|
||
constructor(block: PlaceBlock, x: number, y: number, index: number, posId: number, bx = 0, by = 0) {
|
||
this.block = block
|
||
this.x = x
|
||
this.y = y
|
||
this.placeX = (block ? block.placeX : 0) + x
|
||
this.placeY = (block ? block.placeY : 0) + y
|
||
this.curveIndex = index
|
||
this.posId = posId
|
||
this.bx = bx
|
||
this.by = by
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 放置位置类
|
||
*/
|
||
export class PlacePositionClass {
|
||
// 4. 放置配置映射表
|
||
private placementConfigs: Record<PlaceStyle, PlacementConfig>;
|
||
|
||
constructor() {
|
||
this.placementConfigs = {
|
||
// 正面放置配置
|
||
[PlaceStyle.FRONT]: {
|
||
widthSource: 'cutWidth',
|
||
lengthSource: 'cutLength',
|
||
sealMap: {
|
||
left: 'sealLeft',
|
||
right: 'sealRight',
|
||
top: 'sealTop',
|
||
bottom: 'sealBottom'
|
||
},
|
||
holeCountMap: {
|
||
left: 'holeCountLeft',
|
||
right: 'holeCountRight',
|
||
top: 'holeCountTop',
|
||
bottom: 'holeCountBottom'
|
||
},
|
||
direction: Direction.RIGHT,
|
||
lengthDirection: (block) =>
|
||
block.length > block.width - 0.001 ? Direction.RIGHT : Direction.DOWN
|
||
},
|
||
|
||
// 正面右转配置
|
||
[PlaceStyle.FRONT_TURN_RIGHT]: {
|
||
widthSource: 'cutLength',
|
||
lengthSource: 'cutWidth',
|
||
sealMap: {
|
||
left: 'sealBottom',
|
||
right: 'sealTop',
|
||
top: 'sealLeft',
|
||
bottom: 'sealRight'
|
||
},
|
||
holeCountMap: {
|
||
left: 'holeCountBottom',
|
||
right: 'holeCountTop',
|
||
top: 'holeCountLeft',
|
||
bottom: 'holeCountRight'
|
||
},
|
||
direction: Direction.DOWN,
|
||
lengthDirection: (block) =>
|
||
block.length > block.width - 0.001 ? Direction.DOWN : Direction.LEFT
|
||
},
|
||
|
||
// 正面后转配置
|
||
[PlaceStyle.FRONT_TURN_BACK]: {
|
||
widthSource: 'cutWidth',
|
||
lengthSource: 'cutLength',
|
||
sealMap: {
|
||
left: 'sealRight',
|
||
right: 'sealLeft',
|
||
top: 'sealBottom',
|
||
bottom: 'sealTop'
|
||
},
|
||
holeCountMap: {
|
||
left: 'holeCountRight',
|
||
right: 'holeCountLeft',
|
||
top: 'holeCountBottom',
|
||
bottom: 'holeCountTop'
|
||
},
|
||
direction: Direction.LEFT,
|
||
lengthDirection: (block) =>
|
||
block.length > block.width - 0.001 ? Direction.LEFT : Direction.UP
|
||
},
|
||
|
||
// 正面左转配置
|
||
[PlaceStyle.FRONT_TURN_LEFT]: {
|
||
widthSource: 'cutLength',
|
||
lengthSource: 'cutWidth',
|
||
sealMap: {
|
||
left: 'sealTop',
|
||
right: 'sealBottom',
|
||
top: 'sealRight',
|
||
bottom: 'sealLeft'
|
||
},
|
||
holeCountMap: {
|
||
left: 'holeCountTop',
|
||
right: 'holeCountBottom',
|
||
top: 'holeCountRight',
|
||
bottom: 'holeCountLeft'
|
||
},
|
||
direction: Direction.UP,
|
||
lengthDirection: (block) =>
|
||
block.length > block.width - 0.001 ? Direction.UP : Direction.RIGHT
|
||
},
|
||
|
||
// 反面配置
|
||
[PlaceStyle.BACK]: {
|
||
widthSource: 'cutWidth',
|
||
lengthSource: 'cutLength',
|
||
sealMap: {
|
||
left: 'sealRight',
|
||
right: 'sealLeft',
|
||
top: 'sealTop',
|
||
bottom: 'sealBottom'
|
||
},
|
||
holeCountMap: {
|
||
left: 'holeCountRight',
|
||
right: 'holeCountLeft',
|
||
top: 'holeCountTop',
|
||
bottom: 'holeCountBottom'
|
||
},
|
||
direction: Direction.RIGHT,
|
||
lengthDirection: (block) =>
|
||
block.length > block.width - 0.001 ? Direction.RIGHT : Direction.UP
|
||
},
|
||
|
||
// 反面右转配置
|
||
[PlaceStyle.BACK_TURN_RIGHT]: {
|
||
widthSource: 'cutLength',
|
||
lengthSource: 'cutWidth',
|
||
sealMap: {
|
||
left: 'sealBottom',
|
||
right: 'sealTop',
|
||
top: 'sealRight',
|
||
bottom: 'sealLeft'
|
||
},
|
||
holeCountMap: {
|
||
left: 'holeCountBottom',
|
||
right: 'holeCountTop',
|
||
top: 'holeCountRight',
|
||
bottom: 'holeCountLeft'
|
||
},
|
||
direction: Direction.DOWN,
|
||
lengthDirection: (block) =>
|
||
block.length > block.width - 0.001 ? Direction.DOWN : Direction.RIGHT
|
||
},
|
||
|
||
// 反面后转配置
|
||
[PlaceStyle.BACK_TURN_BACK]: {
|
||
widthSource: 'cutWidth',
|
||
lengthSource: 'cutLength',
|
||
sealMap: {
|
||
left: 'sealLeft',
|
||
right: 'sealRight',
|
||
top: 'sealTop',
|
||
bottom: 'sealBottom'
|
||
},
|
||
holeCountMap: {
|
||
left: 'holeCountLeft',
|
||
right: 'holeCountRight',
|
||
top: 'holeCountTop',
|
||
bottom: 'holeCountBottom'
|
||
},
|
||
direction: Direction.LEFT,
|
||
lengthDirection: (block) =>
|
||
block.length > block.width - 0.001 ? Direction.LEFT : Direction.DOWN
|
||
},
|
||
|
||
// 反面左转配置
|
||
[PlaceStyle.BACK_TURN_LEFT]: {
|
||
widthSource: 'cutLength',
|
||
lengthSource: 'cutWidth',
|
||
sealMap: {
|
||
left: 'sealTop',
|
||
right: 'sealBottom',
|
||
top: 'sealLeft',
|
||
bottom: 'sealRight'
|
||
},
|
||
holeCountMap: {
|
||
left: 'holeCountTop',
|
||
right: 'holeCountBottom',
|
||
top: 'holeCountLeft',
|
||
bottom: 'holeCountRight'
|
||
},
|
||
direction: Direction.UP,
|
||
lengthDirection: (block) =>
|
||
block.length > block.width - 0.001 ? Direction.UP : Direction.LEFT
|
||
}
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 设置块的放置属性
|
||
* @param block 块对象
|
||
* @param newStyle 新的放置样式
|
||
*/
|
||
static setBlockPlacementProperties(block: Block, newStyle: PlaceStyle): Block {
|
||
// 创建一个临时实例来访问 placementConfigs
|
||
const instance = new PlacePositionClass();
|
||
const config = instance.placementConfigs[newStyle];
|
||
if (!config) return block;
|
||
|
||
// 设置尺寸
|
||
block.placeWidth = block[config.widthSource] as number;
|
||
block.placeLength = block[config.lengthSource] as number;
|
||
|
||
// 设置封边
|
||
block.placeSealLeft = block[config.sealMap.left];
|
||
block.placeSealRight = block[config.sealMap.right];
|
||
block.placeSealTop = block[config.sealMap.top];
|
||
block.placeSealBottom = block[config.sealMap.bottom];
|
||
|
||
// 设置孔位计数
|
||
block.holeCountSideLeft = block[config.holeCountMap.left] as number;
|
||
block.holeCountSideRight = block[config.holeCountMap.right] as number;
|
||
block.holeCountSideTop = block[config.holeCountMap.top] as number;
|
||
block.holeCountSideBottom = block[config.holeCountMap.bottom] as number;
|
||
|
||
// 设置方向,严格参照 BlockHelper.resetPlaceStyle
|
||
switch (newStyle) {
|
||
case PlaceStyle.FRONT:
|
||
block.placeDirection = '→';
|
||
block.placeDirection_Length = block.length > block.width - 0.001 ? '→' : '↓';
|
||
break;
|
||
case PlaceStyle.FRONT_TURN_RIGHT:
|
||
block.placeDirection = '↓';
|
||
block.placeDirection_Length = block.length > block.width - 0.001 ? '↓' : '←';
|
||
break;
|
||
case PlaceStyle.FRONT_TURN_BACK:
|
||
block.placeDirection = '←';
|
||
block.placeDirection_Length = block.length > block.width - 0.001 ? '←' : '↑';
|
||
break;
|
||
case PlaceStyle.FRONT_TURN_LEFT:
|
||
block.placeDirection = '↑';
|
||
block.placeDirection_Length = block.length > block.width - 0.001 ? '↑' : '→';
|
||
break;
|
||
case PlaceStyle.BACK:
|
||
block.placeDirection = '→';
|
||
block.placeDirection_Length = block.length > block.width - 0.001 ? '→' : '↑';
|
||
break;
|
||
case PlaceStyle.BACK_TURN_RIGHT:
|
||
block.placeDirection = '↓';
|
||
block.placeDirection_Length = block.length > block.width - 0.001 ? '↓' : '→';
|
||
break;
|
||
case PlaceStyle.BACK_TURN_BACK:
|
||
block.placeDirection = '←';
|
||
block.placeDirection_Length = block.length > block.width - 0.001 ? '←' : '↓';
|
||
break;
|
||
case PlaceStyle.BACK_TURN_LEFT:
|
||
block.placeDirection = '↑';
|
||
block.placeDirection_Length = block.length > block.width - 0.001 ? '↑' : '←';
|
||
break;
|
||
default:
|
||
block.placeDirection = '';
|
||
block.placeDirection_Length = '';
|
||
break;
|
||
}
|
||
|
||
return block;
|
||
}
|
||
|
||
static getOriginalSides(placeStyle: PlaceStyle): number[] {
|
||
// let orgSides = [0, 1, 2, 3];
|
||
let orgSides = [EdgeType.BOTTOM, EdgeType.RIGHT, EdgeType.TOP, EdgeType.LEFT]
|
||
switch (placeStyle) {
|
||
case PlaceStyle.FRONT: // 正面
|
||
break
|
||
case PlaceStyle.FRONT_TURN_RIGHT: // 正面右转
|
||
orgSides[EdgeType.BOTTOM] = EdgeType.RIGHT
|
||
orgSides[EdgeType.RIGHT] = EdgeType.TOP
|
||
orgSides[EdgeType.TOP] = EdgeType.LEFT
|
||
orgSides[EdgeType.LEFT] = EdgeType.BOTTOM
|
||
break
|
||
case PlaceStyle.FRONT_TURN_BACK: // 正面后转
|
||
orgSides[EdgeType.BOTTOM] = EdgeType.TOP
|
||
orgSides[EdgeType.RIGHT] = EdgeType.LEFT
|
||
orgSides[EdgeType.TOP] = EdgeType.BOTTOM
|
||
orgSides[EdgeType.LEFT] = EdgeType.RIGHT
|
||
break
|
||
case PlaceStyle.FRONT_TURN_LEFT: // 正面左转
|
||
orgSides[EdgeType.BOTTOM] = EdgeType.LEFT
|
||
orgSides[EdgeType.RIGHT] = EdgeType.BOTTOM
|
||
orgSides[EdgeType.TOP] = EdgeType.RIGHT
|
||
orgSides[EdgeType.LEFT] = EdgeType.TOP
|
||
break
|
||
case PlaceStyle.BACK: // 反面
|
||
orgSides[EdgeType.BOTTOM] = EdgeType.BOTTOM
|
||
orgSides[EdgeType.RIGHT] = EdgeType.LEFT
|
||
orgSides[EdgeType.TOP] = EdgeType.TOP
|
||
orgSides[EdgeType.LEFT] = EdgeType.RIGHT
|
||
break
|
||
case PlaceStyle.BACK_TURN_RIGHT: // 反面右转
|
||
orgSides[EdgeType.BOTTOM] = EdgeType.LEFT
|
||
orgSides[EdgeType.RIGHT] = EdgeType.TOP
|
||
orgSides[EdgeType.TOP] = EdgeType.RIGHT
|
||
orgSides[EdgeType.LEFT] = EdgeType.BOTTOM
|
||
break
|
||
case PlaceStyle.BACK_TURN_BACK: // 反面后转
|
||
orgSides[EdgeType.BOTTOM] = EdgeType.TOP
|
||
orgSides[EdgeType.RIGHT] = EdgeType.RIGHT
|
||
orgSides[EdgeType.TOP] = EdgeType.BOTTOM
|
||
orgSides[EdgeType.LEFT] = EdgeType.LEFT
|
||
break
|
||
case PlaceStyle.BACK_TURN_LEFT: // 反面左转
|
||
orgSides[EdgeType.BOTTOM] = EdgeType.RIGHT
|
||
orgSides[EdgeType.RIGHT] = EdgeType.BOTTOM
|
||
orgSides[EdgeType.TOP] = EdgeType.LEFT
|
||
orgSides[EdgeType.LEFT] = EdgeType.TOP
|
||
break
|
||
default:
|
||
break
|
||
}
|
||
return orgSides
|
||
}
|
||
/** 翻转小板,翻转动作opType: 0翻面 1右转 2后转 3左转 */
|
||
static turnBlock(block: PlaceBlock, pm: PlaceMaterial, opType: number) {
|
||
let orgStyle = block.placeStyle
|
||
let newStyle = BlockHelper.getTurnedPlaceStyle(orgStyle, opType)
|
||
|
||
let orgPlaceX = block.placeX - block.placeOffX
|
||
let orgPlaceY = block.placeY - block.placeOffY
|
||
|
||
let offset = BlockSizePlus.getOffDis(block, newStyle)
|
||
let newPlaceX = orgPlaceX + offset.x
|
||
let newPlaceY = orgPlaceY + offset.y
|
||
block.placeOffX = offset.x
|
||
block.placeOffY = offset.y
|
||
// 修改小板的放置方式
|
||
BlockHelper.resetPlaceStyle(block, newStyle)
|
||
// 重置放置,检查冲突
|
||
BlockHelper.replaceBlock(pm, block, block.boardId, new Point(newPlaceX, newPlaceY))
|
||
}
|
||
/** 获得翻转后的新放置方式, 翻转动作opType: 0翻面 1右转 2后转 3左转 */
|
||
static getTurnedPlaceStyle(orgStyle: PlaceStyle, opType: number): PlaceStyle {
|
||
|
||
let newStyle: number = orgStyle
|
||
if (opType == 0) // 翻面
|
||
{
|
||
switch (orgStyle) {
|
||
case PlaceStyle.FRONT: // 正面
|
||
newStyle = PlaceStyle.BACK // 反面
|
||
break
|
||
case PlaceStyle.FRONT_TURN_RIGHT: // 正面右转
|
||
newStyle = PlaceStyle.BACK_TURN_LEFT // 反面左转
|
||
break
|
||
case PlaceStyle.FRONT_TURN_BACK: // 正面后转
|
||
newStyle = PlaceStyle.BACK_TURN_BACK // 反面后转
|
||
break
|
||
case PlaceStyle.FRONT_TURN_LEFT: // 正面左转
|
||
newStyle = PlaceStyle.BACK_TURN_RIGHT // 反面右转
|
||
break
|
||
case PlaceStyle.BACK: // 反面
|
||
newStyle = PlaceStyle.FRONT // 正面
|
||
break
|
||
case PlaceStyle.BACK_TURN_RIGHT: // 反面右转
|
||
newStyle = PlaceStyle.FRONT_TURN_LEFT // 正面左转
|
||
break
|
||
case PlaceStyle.BACK_TURN_BACK: // 反面后转
|
||
newStyle = PlaceStyle.FRONT_TURN_BACK // 正面后转
|
||
break
|
||
case PlaceStyle.BACK_TURN_LEFT: // 反面左转
|
||
newStyle = PlaceStyle.FRONT_TURN_RIGHT // 正面右转
|
||
break
|
||
default:
|
||
break
|
||
}
|
||
}
|
||
else if (opType == 1) // 右转
|
||
{
|
||
newStyle = orgStyle + 1
|
||
if (newStyle == 4)
|
||
newStyle = 0
|
||
if (newStyle == 8)
|
||
newStyle = 4
|
||
}
|
||
else if (opType == 2) // 后转
|
||
{
|
||
newStyle = orgStyle + 2
|
||
if (orgStyle < 4 && newStyle >= 4)
|
||
newStyle = newStyle - 4
|
||
if (orgStyle >= 4 && newStyle >= 8)
|
||
newStyle = newStyle - 4
|
||
}
|
||
else if (opType == 3) // 左转
|
||
{
|
||
newStyle = orgStyle - 1
|
||
if (newStyle == 3)
|
||
newStyle = 7
|
||
if (newStyle == -1)
|
||
newStyle = 3
|
||
}
|
||
return newStyle
|
||
}
|
||
static resetPlaceStyle(block: PlaceBlock, newStyle: PlaceStyle) {
|
||
block.placeStyle = newStyle
|
||
let _width = block.cutWidth
|
||
let _lenth = block.cutLength
|
||
if (block.width > block.length) {
|
||
block.cutWidth = Math.max(_width, _lenth)
|
||
block.cutLength = Math.min(_width, _lenth)
|
||
} else {
|
||
block.cutWidth = Math.min(_width, _lenth)
|
||
block.cutLength = Math.max(_width, _lenth)
|
||
}
|
||
let _block: Block = {
|
||
placeWidth: block.placeWidth,
|
||
placeLength: block.placeLength,
|
||
cutWidth: block.cutWidth,
|
||
cutLength: block.cutLength,
|
||
width: block.width,
|
||
length: block.length,
|
||
sealLeft: block.sealLeft,
|
||
sealRight: block.sealRight,
|
||
sealTop: block.sealTop,
|
||
sealBottom: block.sealBottom,
|
||
placeSealLeft: block.placeSealLeft,
|
||
placeSealRight: block.placeSealRight,
|
||
placeSealTop: block.placeSealTop,
|
||
placeSealBottom: block.placeSealBottom,
|
||
holeCountLeft: block.holeCountLeft(),
|
||
holeCountRight: block.holeCountRight(),
|
||
holeCountTop: block.holeCountTop(),
|
||
holeCountBottom: block.holeCountBottom(),
|
||
holeCountSideLeft: block.holeCountSideLeft,
|
||
holeCountSideRight: block.holeCountSideRight,
|
||
holeCountSideTop: block.holeCountSideTop,
|
||
holeCountSideBottom: block.holeCountSideBottom,
|
||
placeDirection: block.placeDirection,
|
||
placeDirection_Length: block.placeDirection_Length
|
||
}
|
||
this.setBlockPlacementProperties(_block, newStyle)
|
||
}
|
||
}
|
||
|
||
// 1. 定义Block接口
|
||
interface Block {
|
||
// 尺寸相关
|
||
placeWidth: number;
|
||
placeLength: number;
|
||
cutWidth: number;
|
||
cutLength: number;
|
||
width: number;
|
||
length: number;
|
||
|
||
// 封边相关
|
||
sealLeft: any;
|
||
sealRight: any;
|
||
sealTop: any;
|
||
sealBottom: any;
|
||
placeSealLeft: any;
|
||
placeSealRight: any;
|
||
placeSealTop: any;
|
||
placeSealBottom: any;
|
||
|
||
// 孔位计数相关
|
||
holeCountLeft: number;
|
||
holeCountRight: number;
|
||
holeCountTop: number;
|
||
holeCountBottom: number;
|
||
holeCountSideLeft: number;
|
||
holeCountSideRight: number;
|
||
holeCountSideTop: number;
|
||
holeCountSideBottom: number;
|
||
|
||
// 方向相关
|
||
placeDirection: string;
|
||
placeDirection_Length: string;
|
||
}
|
||
|
||
// 2. 定义方向枚举(增强类型安全)
|
||
enum Direction {
|
||
RIGHT = '→',
|
||
LEFT = '←',
|
||
UP = '↑',
|
||
DOWN = '↓'
|
||
}
|
||
|
||
// 3. 定义放置配置接口
|
||
interface PlacementConfig {
|
||
widthSource: keyof Block; // 取宽度的来源
|
||
lengthSource: keyof Block; // 取长度的来源
|
||
sealMap: { // 封边映射
|
||
left: keyof Block;
|
||
right: keyof Block;
|
||
top: keyof Block;
|
||
bottom: keyof Block;
|
||
};
|
||
holeCountMap: { // 孔位计数映射
|
||
left: keyof Block;
|
||
right: keyof Block;
|
||
top: keyof Block;
|
||
bottom: keyof Block;
|
||
};
|
||
direction: Direction; // 基础方向
|
||
lengthDirection: (block: Block) => Direction; // 长度方向计算函数
|
||
}
|
||
|
||
|
||
//import { DrawRect } from "../DrawRect";
|
||
|
||
//开料生产
|
||
export class KLSC
|
||
{
|
||
xbang: YH_bang[]; //小板集合
|
||
Bakbang: YH_bang[]; //备份小板集合
|
||
HB_bang: number[] = []; //合并的板
|
||
HB: number[][] = []; //合并板的数组
|
||
B_k: number; //大板宽
|
||
B_g: number; //大板高
|
||
dt: number; //刀头大小(含修边)
|
||
wzx: number; //临时用于打印
|
||
wzy: number; //临时用于打印
|
||
jl_mz: number; //用于测试距离或者面积优选
|
||
|
||
SCid: number[] = []; //用于存化顺序的板的bangid
|
||
//f = () => 5;
|
||
constructor(xbang: YH_bang[], Bang_k: number, Bang_g: number, dt: number, wzx: number, wzy: number, JL_MZ: number) //false JL ture MZ
|
||
{
|
||
this.xbang = JSON.parse(JSON.stringify(xbang));
|
||
//this.xbang = [...xbang];
|
||
this.Bakbang = JSON.parse(JSON.stringify(xbang));
|
||
this.B_g = Bang_g;
|
||
this.B_k = Bang_k;
|
||
this.dt = dt;
|
||
this.wzx = wzx;
|
||
this.wzy = wzy;
|
||
this.jl_mz = JL_MZ;
|
||
this.XDscjs();
|
||
};
|
||
|
||
//查找距离中心最近,且跟最大的板相差不大于容差面积 rcmz 的板 返加YH_bang[].bangid
|
||
MaxMZ = (rcmz: number): number =>
|
||
{
|
||
let tmepckb: number;
|
||
let tmepckb1: number;
|
||
let tempxbang: YH_bang[] = [];
|
||
this.xbang.sort((b, a) => a.pbg * a.pbk - b.pbg * b.pbk);
|
||
let maxmz = this.xbang[0].pbg * this.xbang[0].pbk / 1000000;
|
||
let maxbangid = this.xbang[0].bangid;
|
||
for (let i = 0; i < this.xbang.length; i++)
|
||
{
|
||
if (this.xbang[i].pbg > this.xbang[i].pbk)
|
||
{
|
||
tmepckb = this.xbang[i].pbg / this.xbang[i].pbk;
|
||
}
|
||
else
|
||
{
|
||
tmepckb = this.xbang[i].pbk / this.xbang[i].pbg;
|
||
}
|
||
if (this.xbang[0].pbg > this.xbang[0].pbk)
|
||
{
|
||
tmepckb1 = this.xbang[0].pbg / this.xbang[0].pbk;
|
||
}
|
||
else
|
||
{
|
||
tmepckb1 = this.xbang[0].pbk / this.xbang[0].pbg;
|
||
}
|
||
|
||
if (equaln(this.xbang[i].pbg * this.xbang[i].pbk / 1000000, maxmz, rcmz) && equaln(tmepckb, tmepckb1, 2))
|
||
{
|
||
tempxbang.push(this.xbang[i]);
|
||
}
|
||
}
|
||
if (tempxbang.length > 0)
|
||
{
|
||
return this.minJL(tempxbang);
|
||
}
|
||
else
|
||
{
|
||
return maxbangid;
|
||
}
|
||
|
||
};
|
||
|
||
//查找指定Bangid的板 返回在数组中的位置ID f = () => 5;
|
||
getID = (bangid: number): number => this.xbang.findIndex((n) => n.bangid == bangid);
|
||
|
||
//查找备份板Bangid的板 返回在数组中的位置ID f = () => 5;
|
||
getID_Bkb = (bangid: number): number => this.Bakbang.findIndex((n) => n.bangid == bangid);
|
||
|
||
|
||
//查找距离最近的板 返加YH_bang[].bangid
|
||
minJL = (xbang: YH_bang[]): number => { xbang.sort((b, a) => Math.hypot(this.B_k / 2 - b.x - b.pbk / 2, this.B_g / 2 - b.y - b.pbg / 2) - Math.hypot(this.B_k / 2 - a.x - a.pbk / 2, this.B_g / 2 - a.y - a.pbg / 2)); return xbang[0].bangid; };
|
||
|
||
//查找左边且Y位置一样的板,, 返加YH_bang[].bangid
|
||
F_Left = (bangid: number): number =>
|
||
{
|
||
let a = this.xbang.find((n) => equaln(n.x + n.pbk + this.dt, this.xbang[this.getID(bangid)].x, 0.001)
|
||
&& equaln(n.y, this.xbang[this.getID(bangid)].y, 0.001) && n.ishb == false);
|
||
if (a == undefined) { return; } return a.bangid;
|
||
};
|
||
//查找左边关连的板,并写入
|
||
F_GL_LR = () =>
|
||
{
|
||
let temp: number;
|
||
let bangIndex: number;
|
||
let maxkd: number = 0;
|
||
let maxid: number; //bangid
|
||
if (this.xbang.length > 1)
|
||
{
|
||
for (let i = 0; i < this.xbang.length; i++)
|
||
{
|
||
bangIndex = i;
|
||
while (1) //左边
|
||
{
|
||
if (this.xbang[bangIndex].pbg > this.xbang[bangIndex].pbk && this.xbang[bangIndex].pbk < 200 && this.xbang[bangIndex].ishb == false)
|
||
{
|
||
temp = this.xbang.findIndex(n => n.x + n.pbk < this.xbang[bangIndex].x && n.y <= this.xbang[bangIndex].y && this.XJcd(n.bangid, this.xbang[bangIndex].bangid)[1] > this.xbang[bangIndex].pbk);
|
||
if (temp != -1)
|
||
{
|
||
if (this.xbang[temp].pbk > maxkd)
|
||
{
|
||
maxkd = this.xbang[temp].pbk;
|
||
maxid = this.xbang[temp].bangid;
|
||
}
|
||
if (this.xbang[temp].pbk > 200)
|
||
{
|
||
this.xbang[temp].isgr = true;
|
||
this.xbang[temp].gr.push(this.xbang[bangIndex].bangid);
|
||
this.xbang[bangIndex].grid = this.xbang[temp].bangid;
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
bangIndex = temp;
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
break;
|
||
}
|
||
|
||
}
|
||
bangIndex = i;
|
||
while (1) //右边
|
||
{
|
||
if (this.xbang[bangIndex].pbg > this.xbang[bangIndex].pbk && this.xbang[bangIndex].pbk < 200 && this.xbang[bangIndex].ishb == false)
|
||
{
|
||
temp = this.xbang.findIndex(n => n.x > this.xbang[bangIndex].x + this.xbang[bangIndex].pbk
|
||
&& this.LR_is(this.xbang[bangIndex].bangid, n.bangid) == false
|
||
&& n.pbg > 300
|
||
&& this.XJcd(n.bangid, this.xbang[bangIndex].bangid)[1] > this.xbang[bangIndex].pbk);
|
||
if (temp != -1)
|
||
{
|
||
if (this.xbang[temp].pbk > maxkd)
|
||
{
|
||
maxkd = this.xbang[temp].pbk;
|
||
maxid = this.xbang[temp].bangid;
|
||
}
|
||
if (this.xbang[temp].pbk > 200)
|
||
{
|
||
this.xbang[temp].isgr = true;
|
||
this.xbang[temp].gr.push(this.xbang[bangIndex].bangid);
|
||
this.xbang[bangIndex].grid = this.xbang[temp].bangid;
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
bangIndex = temp;
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
break;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
}
|
||
};
|
||
};
|
||
|
||
//查找上下边关连的板,并写入
|
||
F_GL_TD = () =>
|
||
{
|
||
let temp: number;
|
||
let bangIndex: number;
|
||
let maxkd: number = 0;
|
||
let maxid: number; //bangid
|
||
if (this.xbang.length > 1)
|
||
{
|
||
for (let i = 0; i < this.xbang.length; i++)
|
||
{
|
||
bangIndex = i;
|
||
while (1) //上面
|
||
{
|
||
if (this.xbang[bangIndex].pbg < this.xbang[bangIndex].pbk && this.xbang[bangIndex].pbg < 200 && this.xbang[bangIndex].ishb == false)
|
||
{
|
||
temp = this.xbang.findIndex(n => n.y > this.xbang[bangIndex].y + this.xbang[bangIndex].pbg && n.x + 0.01 <= this.xbang[bangIndex].x
|
||
&& this.XJcd(n.bangid, this.xbang[bangIndex].bangid)[0] > this.xbang[bangIndex].pbg);
|
||
if (temp != -1)
|
||
{
|
||
if (this.xbang[temp].pbg > maxkd)
|
||
{
|
||
maxkd = this.xbang[temp].pbg;
|
||
maxid = this.xbang[temp].bangid;
|
||
}
|
||
if (this.xbang[temp].pbg > 200)
|
||
{
|
||
this.xbang[temp].isgr = true;
|
||
this.xbang[temp].gr.push(this.xbang[bangIndex].bangid);
|
||
this.xbang[bangIndex].grid = this.xbang[temp].bangid;
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
bangIndex = temp;
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
break;
|
||
}
|
||
|
||
}
|
||
bangIndex = i;
|
||
while (1) //下面
|
||
{
|
||
|
||
if (this.xbang[bangIndex].pbg < this.xbang[bangIndex].pbk && this.xbang[bangIndex].pbg < 200 && this.xbang[bangIndex].ishb == false)
|
||
{
|
||
|
||
temp = this.xbang.findIndex(n => n.y + n.pbg < this.xbang[bangIndex].y + this.xbang[bangIndex].pbg && n.x - 0.01 <= this.xbang[bangIndex].x
|
||
&& this.XJcd(n.bangid, this.xbang[bangIndex].bangid)[0] > this.xbang[bangIndex].pbg);
|
||
if (temp != -1)
|
||
{
|
||
if (this.xbang[temp].pbg > maxkd)
|
||
{
|
||
maxkd = this.xbang[temp].pbg;
|
||
maxid = this.xbang[temp].bangid;
|
||
}
|
||
if (this.xbang[temp].pbg > 200)
|
||
{
|
||
this.xbang[temp].isgr = true;
|
||
this.xbang[temp].gr.push(this.xbang[bangIndex].bangid);
|
||
this.xbang[bangIndex].grid = this.xbang[temp].bangid;
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
bangIndex = temp;
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
break;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
}
|
||
};
|
||
};
|
||
|
||
//查找有异形交集关连的板,并写入
|
||
F_GL_JJB = () =>
|
||
{
|
||
let temp: number;
|
||
if (this.xbang.length > 1)
|
||
{
|
||
for (let i = 0; i < this.xbang.length; i++)
|
||
{
|
||
temp = this.xbang.findIndex(n => this.XJcd(n.bangid, this.xbang[i].bangid)[0] > 50
|
||
&& this.XJcd(n.bangid, this.xbang[i].bangid)[1] > 50 && n.bangid != this.xbang[i].bangid);
|
||
if (temp != -1)
|
||
{
|
||
if (this.xbang[i].pbg * this.xbang[i].pbk > this.xbang[temp].pbg * this.xbang[temp].pbk)
|
||
{
|
||
this.xbang[i].isgr = true;
|
||
this.xbang[i].gr.push(this.xbang[temp].bangid);
|
||
this.xbang[temp].grid = this.xbang[i].bangid;
|
||
}
|
||
else if (equaln(this.xbang[i].pbg * this.xbang[i].pbk, this.xbang[temp].pbg * this.xbang[temp].pbk, 0.01))
|
||
{
|
||
if (this.xbang[temp].x > this.xbang[i].x)
|
||
{
|
||
|
||
this.xbang[i].isgr = true;
|
||
this.xbang[i].gr.push(this.xbang[temp].bangid);
|
||
this.xbang[temp].grid = this.xbang[i].bangid;
|
||
}
|
||
else
|
||
{
|
||
this.xbang[temp].isgr = true;
|
||
this.xbang[temp].gr.push(this.xbang[i].bangid);
|
||
this.xbang[i].grid = this.xbang[temp].bangid;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
this.xbang[temp].isgr = true;
|
||
this.xbang[temp].gr.push(this.xbang[i].bangid);
|
||
this.xbang[i].grid = this.xbang[temp].bangid;
|
||
}
|
||
|
||
}
|
||
}
|
||
};
|
||
for (let k = 0; k < this.xbang.length; k++)
|
||
{
|
||
let newgr = [... new Set(this.xbang[k].gr)];
|
||
this.xbang[k].gr = newgr;
|
||
}
|
||
};
|
||
|
||
//判断有关联的板跟大板之间是否有交集,如果有取消这块板的关联
|
||
Is_big_gr = () =>
|
||
{
|
||
for (let k = 0; k < this.xbang.length; k++)
|
||
{
|
||
let newgr = [... new Set(this.xbang[k].gr)];
|
||
this.xbang[k].gr = newgr;
|
||
}
|
||
let tempx: number;
|
||
let tempy: number;
|
||
let bangIndex1 = this.xbang[this.getID(this.HB[0][0])];
|
||
let bangIndex2: number;
|
||
for (let i = 0; i < this.xbang.length; i++)
|
||
{
|
||
if (this.xbang[i].isgr == true)
|
||
{
|
||
tempx = 0;
|
||
tempy = 0;
|
||
for (let j = 0; j < this.xbang[i].gr.length; j++)
|
||
{
|
||
bangIndex2 = this.getID(this.xbang[i].gr[j]);
|
||
if (this.xbang[i].bangid == 10)////////////////////用于调试
|
||
{
|
||
console.log(this.xbang[i].bangid);
|
||
}
|
||
if (this.xbang[bangIndex2].pbg > this.xbang[bangIndex2].pbk)
|
||
{
|
||
tempy = this.Jcxj(bangIndex1.y, bangIndex1.pbg, this.xbang[bangIndex2].y, this.xbang[bangIndex2].pbg);
|
||
}
|
||
else
|
||
{
|
||
tempx = this.Jcxj(bangIndex1.x, bangIndex1.pbk, this.xbang[bangIndex2].x, this.xbang[bangIndex2].pbk);
|
||
}
|
||
}
|
||
if (tempx > 50 || tempy > 50)
|
||
{
|
||
this.xbang[i].isgr = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
};
|
||
|
||
|
||
//检测两块板之间的右上角是否有板 false 没有 true 有
|
||
LR_is = (bangid1: number, bangid2: number): boolean =>
|
||
{
|
||
let tb: YH_bang[] = [];
|
||
tb.push(this.xbang[this.getID(bangid1)]);
|
||
tb.push(this.xbang[this.getID(bangid2)]);
|
||
if (tb[0].pbg + tb[0].y > tb[1].pbg + tb[1].y)//右上空间 左边高
|
||
{
|
||
return this.JCQY_is_bang(tb[1].x, tb[1].y + tb[1].pbg + this.dt, tb[1].pbk, tb[0].pbg - tb[1].pbg - this.dt);
|
||
}
|
||
else
|
||
{
|
||
return false;
|
||
}
|
||
};
|
||
|
||
//检测两块板之间的右上角是否有板 false 没有 true 有
|
||
TD_is = (bangid1: number, bangid2: number): boolean =>
|
||
{
|
||
let tb: YH_bang[] = [];
|
||
tb.push(this.xbang[this.getID(bangid1)]);
|
||
tb.push(this.xbang[this.getID(bangid2)]);
|
||
if (tb[0].pbk + tb[0].x > tb[1].pbk + tb[1].x)//右下空间 左边高
|
||
{
|
||
return this.JCQY_is_bang(tb[1].x, tb[1].y + tb[1].pbg + this.dt, tb[1].pbk, tb[0].pbg - tb[1].pbg - this.dt);
|
||
}
|
||
else
|
||
{
|
||
return false;
|
||
}
|
||
};
|
||
|
||
//查找左边且Y位置一样的板,, 返加YH_bang[].bangid
|
||
F_Left_Big = (bangid: number, gbcd: number): number =>
|
||
{
|
||
let tempjh: YH_bang[] = [];
|
||
for (let i = 0; i < this.xbang.length; i++)
|
||
{
|
||
if (this.xbang[i].x + this.xbang[i].pbk < this.xbang[this.getID(bangid)].x && this.XJcd(this.xbang[i].bangid, this.xbang[this.getID(bangid)].bangid)[1] > gbcd)
|
||
{
|
||
tempjh.push(this.xbang[i]);
|
||
}
|
||
}
|
||
if (tempjh.length > 0)
|
||
{
|
||
tempjh.sort((a, b) => a.x - b.x);
|
||
return tempjh[0].bangid;
|
||
}
|
||
else
|
||
{
|
||
return -1;
|
||
}
|
||
};
|
||
|
||
//找到左右靠边最长的高度 返回 [0]长度 [1] y位置 [2] 0左边 1 右边
|
||
L_R_kbcd = (bangid: number): [number, number, number] =>
|
||
{
|
||
let l_b: YH_bang[] = [];
|
||
let cd_l = 0; let cd_r: number = 0; let wzl: number; let wzr: number;
|
||
let tb = [...this.xbang];
|
||
let tempx: number = this.xbang[this.getID(bangid)].x;
|
||
let tempy: number = this.xbang[this.getID(bangid)].y;
|
||
let tempk: number = this.xbang[this.getID(bangid)].pbk;
|
||
let tempid: number;
|
||
let isend: boolean = true;
|
||
for (let i = 0; i < 2; i++)
|
||
{
|
||
l_b = [];
|
||
tb = [...this.xbang];
|
||
isend = true;
|
||
while (isend == true)
|
||
{
|
||
if (i == 0) { tempid = tb.findIndex((n) => equaln(n.x + n.pbk + this.dt, tempx, 0.001) && (n.y <= tempy)); }
|
||
else { tempid = tb.findIndex((n) => equaln(n.x, tempx + tempk + this.dt, 0.001) && (n.y <= tempy)); }
|
||
|
||
if (tempid != -1)
|
||
{
|
||
l_b.push(tb[tempid]);
|
||
tb.splice(tempid, 1);
|
||
}
|
||
else
|
||
{
|
||
isend = false;
|
||
}
|
||
}
|
||
if (l_b.length > 0)
|
||
{
|
||
l_b.sort((a, b) => b.pbg - a.pbg);
|
||
if (i == 0) { cd_l = l_b[0].pbg; wzl = l_b[0].y; } else { cd_r = l_b[0].pbg; wzr = l_b[0].y; }
|
||
}
|
||
}
|
||
if (cd_l > cd_r || cd_l == cd_r && cd_l > 0)
|
||
{
|
||
return [cd_l, wzl, 0];
|
||
}
|
||
else if (cd_l < cd_r)
|
||
{
|
||
return [cd_r, wzr, 1];
|
||
}
|
||
else
|
||
{
|
||
return [0, 0, 0];
|
||
}
|
||
|
||
};
|
||
|
||
//查找右边且Y位置一样的板,, 返加YH_bang[].bangid
|
||
F_Right = (bangid: number): number =>
|
||
{
|
||
let a = this.xbang.find((n) => equaln(n.x, this.xbang[this.getID(bangid)].x + this.xbang[this.getID(bangid)].pbk + this.dt, 0.001)
|
||
&& equaln(n.y, this.xbang[this.getID(bangid)].y, 0.001) && n.ishb == false);
|
||
if (a == undefined) { return; } return a.bangid;
|
||
};
|
||
|
||
//查找右边且Y位置一样的板,, 返加YH_bang[].bangid
|
||
F_Right_Big = (bangid: number, gbcd: number): number =>
|
||
{
|
||
let tempjh: YH_bang[] = [];
|
||
for (let i = 0; i < this.xbang.length; i++)
|
||
{
|
||
if (this.xbang[i].x > this.xbang[this.getID(bangid)].x + this.xbang[this.getID(bangid)].pbk && this.XJcd(this.xbang[i].bangid, this.xbang[this.getID(bangid)].bangid)[1] > gbcd)
|
||
{
|
||
tempjh.push(this.xbang[i]);
|
||
}
|
||
}
|
||
if (tempjh.length > 0)
|
||
{
|
||
tempjh.sort((a, b) => a.x - b.x);
|
||
return tempjh[0].bangid;
|
||
}
|
||
else
|
||
{
|
||
return -1;
|
||
}
|
||
};
|
||
|
||
//查找下边且X位置一样的板,, 返加YH_bang[].bangid
|
||
F_Down = (bangid: number): number =>
|
||
{
|
||
let a = this.xbang.find((n) => equaln(n.y + n.pbg + this.dt, this.xbang[this.getID(bangid)].y, 0.001)
|
||
// && n.x > 10
|
||
&& equaln(n.x, this.xbang[this.getID(bangid)].x, 0.001) && n.ishb == false);
|
||
if (a == undefined) { return; } return a.bangid;
|
||
};
|
||
|
||
//查找上边且X位置一样的板,, 返加YH_bang[].bangid
|
||
F_TOP = (bangid: number): number =>
|
||
{
|
||
let a = this.xbang.find((n) => equaln(n.y, this.xbang[this.getID(bangid)].y + this.xbang[this.getID(bangid)].pbg + this.dt, 0.001)
|
||
//&& n.x > 10
|
||
&& equaln(n.x, this.xbang[this.getID(bangid)].x, 0.001) && n.ishb == false);
|
||
if (a == undefined) { return; } return a.bangid;
|
||
};
|
||
|
||
|
||
//查找上边且X位置一样的板,, 返加YH_bang[].bangid hbcd为大于共边的长度
|
||
F_Top_Big = (bangid: number, gbcd: number): number =>
|
||
{
|
||
let tempjh: YH_bang[] = [];
|
||
for (let i = 0; i < this.xbang.length; i++)
|
||
{
|
||
if (this.xbang[i].y > this.xbang[this.getID(bangid)].y + this.xbang[this.getID(bangid)].pbg
|
||
&& this.xbang[i].x + this.xbang[i].pbk <= this.xbang[this.getID(bangid)].x + this.xbang[this.getID(bangid)].pbk + 0.1
|
||
&& this.XJcd(this.xbang[i].bangid, this.xbang[this.getID(bangid)].bangid)[0] > gbcd)
|
||
{
|
||
tempjh.push(this.xbang[i]);
|
||
}
|
||
}
|
||
if (tempjh.length > 0)
|
||
{
|
||
tempjh.sort((a, b) => a.x - b.x);
|
||
return tempjh[0].bangid;
|
||
}
|
||
else
|
||
{
|
||
return -1;
|
||
}
|
||
};
|
||
|
||
|
||
//查找下边且X位置一样的板,, 返加YH_bang[].bangid
|
||
F_Down_Big = (bangid: number, gbcd: number): number =>
|
||
{
|
||
let tempjh: YH_bang[] = [];
|
||
for (let i = 0; i < this.xbang.length; i++)
|
||
{
|
||
for (let i = 0; i < this.xbang.length; i++)
|
||
{
|
||
if (this.xbang[i].y + this.xbang[i].pbg < this.xbang[this.getID(bangid)].y
|
||
&& this.xbang[i].x >= this.xbang[this.getID(bangid)].x && this.xbang[i].pbg > 300
|
||
&& this.XJcd(this.xbang[i].bangid, this.xbang[this.getID(bangid)].bangid)[0] > gbcd)
|
||
{
|
||
tempjh.push(this.xbang[i]);
|
||
}
|
||
}
|
||
}
|
||
if (tempjh.length > 0)
|
||
{
|
||
tempjh.sort((a, b) => a.x - b.x);
|
||
return tempjh[0].bangid;
|
||
}
|
||
else
|
||
{
|
||
return -1;
|
||
}
|
||
};
|
||
|
||
|
||
//合并同高相邻的板 isbig: true 为第一回合并的大板 wz为方位 L 左 R右 T上 D下 返回是否有合并过 false 为没有合并过 true 有合并过
|
||
HB_LR = (bangid: number, isbig: boolean): boolean =>
|
||
{
|
||
let isend: boolean = true;
|
||
let tempbangid: number;
|
||
let ishb: boolean = false;
|
||
|
||
while (isend == true)
|
||
{
|
||
tempbangid = this.F_Left(bangid);
|
||
if (tempbangid != undefined)
|
||
{
|
||
let temp = this.JC_is_bang(bangid, tempbangid); //[f/t,1:x,2:y,3:k,4:g]
|
||
if (temp[0] == false)
|
||
{
|
||
this.addbang(bangid, tempbangid, temp[1], temp[2], temp[3], temp[4], isbig);
|
||
ishb = true;
|
||
}
|
||
else
|
||
{
|
||
isend = false;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
isend = false;
|
||
}
|
||
}
|
||
isend = true;
|
||
while (isend == true)
|
||
{
|
||
tempbangid = this.F_Right(bangid);
|
||
if (tempbangid != undefined)
|
||
{
|
||
let temp = this.JC_is_bang(bangid, tempbangid); //[f/t,1:x,2:y,3:k,4:g]
|
||
if (temp[0] == false)
|
||
{
|
||
this.addbang(bangid, tempbangid, temp[1], temp[2], temp[3], temp[4], isbig);
|
||
ishb = true;
|
||
}
|
||
else
|
||
{
|
||
isend = false;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
isend = false;
|
||
}
|
||
}
|
||
return ishb;
|
||
};
|
||
|
||
//合并同宽相邻的板 isbig: true 为第一回合并的大板 wz为方位 L 左 R右 T上 D下 返回是否有合并过 false 为没有合并过 true 有合并过
|
||
HB_TD = (bangid: number, isbig: boolean): boolean =>
|
||
{
|
||
let isend: boolean = true;
|
||
let tempbangid: number;
|
||
let ishb: boolean = false;
|
||
while (isend == true)
|
||
{
|
||
tempbangid = this.F_Down(bangid);
|
||
if (tempbangid != undefined)
|
||
{
|
||
let temp = this.JC_is_bang(bangid, tempbangid); //[f/t,1:x,2:y,3:k,4:g]
|
||
if (temp[0] == false)
|
||
{
|
||
this.addbang(bangid, tempbangid, temp[1], temp[2], temp[3], temp[4], isbig);
|
||
ishb = true;
|
||
}
|
||
else
|
||
{
|
||
isend = false;
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
isend = false;
|
||
}
|
||
}
|
||
isend = true;
|
||
while (isend == true)
|
||
{
|
||
tempbangid = this.F_TOP(bangid);
|
||
if (tempbangid != undefined)
|
||
{
|
||
let temp = this.JC_is_bang(bangid, tempbangid); //[f/t,1:x,2:y,3:k,4:g]
|
||
if (temp[0] == false)
|
||
{
|
||
this.addbang(bangid, tempbangid, temp[1], temp[2], temp[3], temp[4], isbig);
|
||
ishb = true;
|
||
}
|
||
else
|
||
{
|
||
isend = false;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
isend = false;
|
||
}
|
||
}
|
||
return ishb;
|
||
};
|
||
|
||
addbang = (id1: number, id2: number, x: number, y: number, k: number, g: number, isbig: boolean) => //把合并的板写入,并改板的大小
|
||
{
|
||
let tempid1 = this.getID(id1);
|
||
let tempid2 = this.getID(id2);
|
||
if (this.xbang[tempid1].ishb == false)
|
||
{
|
||
this.HB_bang.push(id1);
|
||
}
|
||
this.HB_bang.push(id2);
|
||
this.xbang[tempid1].x = x;
|
||
this.xbang[tempid1].y = y;
|
||
this.xbang[tempid1].pbk = k;
|
||
this.xbang[tempid1].pbg = g;
|
||
this.xbang[tempid1].ishb = true;
|
||
this.xbang[tempid2].ishb = true;
|
||
if (isbig == true) { this.xbang[tempid1].isbig = true; this.xbang[tempid2].isbig = true; }
|
||
};
|
||
|
||
//计算相邻两块板中有空位的地方是否有其它小板 返回 false 为没有其它板,true 有其它板 x,y,k,g
|
||
JC_is_bang = (bangid1: number, bangid2: number): [boolean, number, number, number, number] =>
|
||
{
|
||
let tb: YH_bang[] = [];
|
||
tb.push(this.xbang[this.getID(bangid1)]);
|
||
tb.push(this.xbang[this.getID(bangid2)]);
|
||
if (equaln(tb[0].y, tb[1].y, 0.01)) //左右相邻
|
||
{
|
||
tb.sort((a, b) => a.x - b.x);
|
||
if (tb[0].pbg < tb[1].pbg)//左上空间 右边高
|
||
{
|
||
return [this.JCQY_is_bang(tb[0].x, tb[0].y + tb[0].pbg + this.dt, tb[0].pbk, tb[1].pbg - tb[0].pbg - this.dt),
|
||
tb[0].x, tb[0].y, tb[0].pbk + tb[1].pbk + this.dt, tb[1].pbg];
|
||
}
|
||
else if (tb[0].pbg > tb[1].pbg)//右上空间 左边高
|
||
{
|
||
return [this.JCQY_is_bang(tb[1].x, tb[1].y + tb[1].pbg + this.dt, tb[1].pbk, tb[0].pbg - tb[1].pbg - this.dt),
|
||
tb[0].x, tb[0].y, tb[0].pbk + tb[1].pbk + this.dt, tb[0].pbg];
|
||
}
|
||
else //一样高
|
||
{
|
||
return [false, tb[0].x, tb[0].y, tb[0].pbk + tb[1].pbk + this.dt, tb[0].pbg];
|
||
}
|
||
}
|
||
else //上下空间
|
||
{
|
||
tb.sort((b, a) => a.y - b.y);
|
||
if (tb[0].pbk < tb[1].pbk)//右上空间 上边短
|
||
{
|
||
return [this.JCQY_is_bang(tb[0].x + tb[0].pbk + this.dt, tb[0].y, tb[1].pbk - tb[0].pbk - this.dt, tb[0].pbg),
|
||
tb[1].x, tb[1].y, tb[1].pbk, tb[0].pbg + tb[1].pbg + this.dt];
|
||
}
|
||
else if (tb[0].pbk > tb[1].pbk)//右下空间 下边短
|
||
{
|
||
return [this.JCQY_is_bang(tb[1].x + tb[1].pbk + this.dt, tb[1].y, tb[0].pbk - tb[1].pbk - this.dt, tb[1].pbg),
|
||
tb[1].x, tb[1].y, tb[0].pbk, tb[0].pbg + tb[1].pbg + this.dt];
|
||
}
|
||
else //一样高
|
||
{
|
||
return [false, tb[1].x, tb[1].y, tb[0].pbk, tb[0].pbg + tb[1].pbg + this.dt];
|
||
}
|
||
}
|
||
};
|
||
|
||
//检测两块板之间相交的长度且两块板之间没有其它板 ,返回长度,第一个为X相交长度 第二个为Y相交长度
|
||
XJcd = (bangid1: number, bangid2: number): [number, number] =>
|
||
{
|
||
let tempbang: YH_bang[] = [];
|
||
tempbang.push(this.xbang[this.getID(bangid1)]);
|
||
tempbang.push(this.xbang[this.getID(bangid2)]);
|
||
|
||
let tempx = this.Jcxj(tempbang[0].x, tempbang[0].pbk, tempbang[1].x, tempbang[1].pbk);
|
||
let tempy = this.Jcxj(tempbang[0].y, tempbang[0].pbg, tempbang[1].y, tempbang[1].pbg);
|
||
if (tempx > 0 && tempy > 0)
|
||
{
|
||
return [tempx, tempy];
|
||
}
|
||
else if (tempx > 0)
|
||
{
|
||
tempbang.sort((a, b) => a.x - b.x);
|
||
if (tempbang[0].y > tempbang[1].y)
|
||
{
|
||
if (this.JCQY_is_bang(tempbang[1].x, tempbang[1].y + tempbang[1].pbg, tempx, tempbang[0].y - tempbang[1].y - tempbang[1].pbg) == false)
|
||
{
|
||
return [tempx, 0];
|
||
}
|
||
else
|
||
{
|
||
return [0, 0];
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (this.JCQY_is_bang(tempbang[1].x, tempbang[0].y + tempbang[0].pbg, tempx, tempbang[1].y - tempbang[0].y - tempbang[0].pbg) == false)
|
||
{
|
||
return [tempx, 0];
|
||
}
|
||
else
|
||
{
|
||
return [0, 0];
|
||
}
|
||
}
|
||
|
||
}
|
||
else if (tempy > 0)
|
||
{
|
||
tempbang.sort((a, b) => a.x - b.x);
|
||
if (tempbang[0].y > tempbang[1].y)
|
||
{
|
||
if (this.JCQY_is_bang(tempbang[0].x + tempbang[0].pbk, tempbang[0].y, tempbang[1].x - tempbang[0].x - tempbang[0].pbk, tempy) == false)
|
||
{
|
||
return [0, tempy];
|
||
}
|
||
else
|
||
{
|
||
return [0, 0];
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (this.JCQY_is_bang(tempbang[0].x + tempbang[0].pbk, tempbang[1].y, tempbang[1].x - tempbang[0].x - tempbang[0].pbk, tempy) == false)
|
||
{
|
||
return [0, tempy];
|
||
}
|
||
else
|
||
{
|
||
return [0, 0];
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
return [0, 0];
|
||
}
|
||
};
|
||
|
||
//检测指定区域内否有其它小板 返回 false 为没有其它板,true 有其它板
|
||
JCQY_is_bang = (x: number, y: number, k: number, g: number): boolean =>
|
||
{
|
||
let result = this.xbang.findIndex((n) => (k + n.pbk - Math.abs(x - n.x) - Math.abs(x - n.x + k - n.pbk)) / 2 > 0.01 &&
|
||
(g + n.pbg - Math.abs(y - n.y) - Math.abs(y - n.y + g - n.pbg)) / 2 > 0.01);
|
||
if (result == -1) { return false; } else { return true; }
|
||
};
|
||
|
||
//计算两边相交长度/
|
||
Jcxj = (wz1: number, l1: number, wz2: number, l2: number): number => { return (l1 + l2 - Math.abs(wz1 - wz2) - Math.abs(wz1 - wz2 + l1 - l2)) / 2; };
|
||
|
||
Find_BS = (): number[] =>
|
||
{
|
||
let temp = this.Find_BS_gr();
|
||
if (temp[0] > 2)
|
||
{
|
||
return this.Find_BS_wgr()[1];
|
||
}
|
||
else
|
||
{
|
||
if (temp[1][0] == 0)
|
||
{
|
||
return this.Find_BS_wgr()[1];
|
||
}
|
||
else
|
||
{
|
||
return temp[1];
|
||
}
|
||
|
||
|
||
}
|
||
};
|
||
//找到共边最少的板的集合 订算有关系的板
|
||
Find_BS_gr = (): [number, number[]] =>
|
||
{
|
||
let bs: number = 6;
|
||
let id: number[] = [];
|
||
let tempsl: number[];
|
||
if (this.xbang.length == 1)
|
||
{
|
||
return [0, [0]];
|
||
}
|
||
else
|
||
{
|
||
for (let i = 0; i < this.xbang.length; i++)
|
||
{
|
||
if (this.xbang[i].isgr == false && this.xbang[i].ishb == false && this.xbang[i].isqg == false)
|
||
{
|
||
tempsl = this.JSgbsl(this.xbang[i].bangid);
|
||
if (bs == tempsl[0])
|
||
{
|
||
id.push(this.xbang[i].bangid);
|
||
}
|
||
else if (bs > tempsl[0])
|
||
{
|
||
bs = tempsl[0];
|
||
id = [];
|
||
id.push(this.xbang[i].bangid);
|
||
}
|
||
|
||
}
|
||
}
|
||
if (id.length > 0)
|
||
{ return [bs, id]; }
|
||
else
|
||
{
|
||
//console.log("没找到最少边");
|
||
return [0, [0]];
|
||
}
|
||
|
||
}
|
||
};
|
||
|
||
//找到共边最少的板的集合 订算没有算关系的板
|
||
Find_BS_wgr = (): [number, number[]] =>
|
||
{
|
||
let bs: number = 6;
|
||
let id: number[] = [];
|
||
let tempsl: number[];
|
||
if (this.xbang.length == 1)
|
||
{
|
||
return [0, [0]];
|
||
}
|
||
else
|
||
{
|
||
for (let i = 0; i < this.xbang.length; i++)
|
||
{
|
||
if (this.xbang[i].ishb == false && this.xbang[i].isqg == false)
|
||
{
|
||
tempsl = this.JSgbsl(this.xbang[i].bangid);
|
||
if (bs == tempsl[0])
|
||
{
|
||
id.push(this.xbang[i].bangid);
|
||
}
|
||
else if (bs > tempsl[0])
|
||
{
|
||
bs = tempsl[0];
|
||
id = [];
|
||
id.push(this.xbang[i].bangid);
|
||
}
|
||
}
|
||
}
|
||
if (id.length > 0) { return [bs, id]; } else { return [0, [0]]; }
|
||
|
||
}
|
||
};
|
||
|
||
|
||
//计算这块板的与其它板的相交的边数,及每条边数跟权重 0数量 1左 2右 3上 4下 5权重
|
||
JSgbsl = (bangid: number): [number, number, number, number, number, number] =>
|
||
{
|
||
let left = 0, right = 0, top = 0, down = 0, qz = 0;
|
||
let bangIndex = this.getID(bangid);
|
||
for (let j = 0; j < this.xbang.length; j++)
|
||
{
|
||
if (bangIndex != j && this.xbang[j].isqg == false)
|
||
{
|
||
let jjy = this.Jcxj(this.xbang[bangIndex].y, this.xbang[bangIndex].pbg, this.xbang[j].y, this.xbang[j].pbg);
|
||
let jjx = this.Jcxj(this.xbang[bangIndex].x, this.xbang[bangIndex].pbk, this.xbang[j].x, this.xbang[j].pbk);
|
||
if (this.xbang[bangIndex].pbg > this.xbang[bangIndex].pbk)
|
||
{
|
||
if (jjy < this.xbang[bangIndex].pbk && jjy < 50) { jjy = 0; }
|
||
}
|
||
if (this.xbang[bangIndex].pbk > this.xbang[bangIndex].pbg)
|
||
{
|
||
if (jjx < this.xbang[bangIndex].pbg && jjx < 50) { jjx = 0; }
|
||
}
|
||
if (jjy > 0 && this.xbang[bangIndex].x > this.xbang[j].x + this.xbang[j].pbk) { left = 1; }
|
||
if (jjy > 0 && this.xbang[j].x > this.xbang[bangIndex].x + this.xbang[bangIndex].pbk) { right = 1; }
|
||
if (jjx > 0 && this.xbang[bangIndex].y > this.xbang[j].y + this.xbang[j].pbg) { down = 1; }
|
||
if (jjx > 0 && this.xbang[j].y > this.xbang[bangIndex].y + this.xbang[bangIndex].pbg) { top = 1; }
|
||
if ((left == 1 && right == 1) || (down == 1 && top == 1)) { qz = 1; }
|
||
}
|
||
}
|
||
return [left + right + top + down + qz, left, right, top, down, qz];
|
||
};
|
||
Jcsb = (bangid1: number, bangid2: number): boolean => // 把bang1 要去掉, bang2 是否少边 返加True 有少边 False 没有少边
|
||
{
|
||
let xj = this.XJcd(bangid1, bangid2);
|
||
let jjx = xj[0]; let jjy = xj[1];
|
||
|
||
|
||
if (jjx > 0 && this.xbang[this.getID(bangid1)].pbg < this.xbang[this.getID(bangid2)].pbg)
|
||
{
|
||
return true;
|
||
}
|
||
else if (jjx > 0 && jjx > 0 && this.xbang[this.getID(bangid1)].pbk * this.xbang[this.getID(bangid1)].pbg < this.xbang[this.getID(bangid2)].pbk * this.xbang[this.getID(bangid2)].pbg)
|
||
{
|
||
return false;
|
||
}
|
||
else if (jjy > 0 && this.xbang[this.getID(bangid1)].pbg < this.xbang[this.getID(bangid2)].pbg)
|
||
{
|
||
return false;
|
||
}
|
||
else if (jjy > 0 && this.xbang[this.getID(bangid1)].pbg > this.xbang[this.getID(bangid2)].pbg)
|
||
{
|
||
return true;
|
||
}
|
||
// else if (jjy > 0 && this.xbang[this.getID(bangid2)].pbk > this.xbang[this.getID(bangid2)].pbg
|
||
// && this.xbang[this.getID(bangid2)].pbk * this.xbang[this.getID(bangid2)].pbg < this.xbang[this.getID(bangid1)].pbk * this.xbang[this.getID(bangid1)].pbg)
|
||
// {
|
||
// return true;
|
||
// }
|
||
else
|
||
{
|
||
return false;
|
||
}
|
||
|
||
|
||
|
||
// if (bangid1 == 2 && bangid2 == 10)
|
||
// {
|
||
// console.log(bangid1);
|
||
// }
|
||
// let bs1 = this.JSgbsl(bangid1)[0];
|
||
// let bs2 = this.JSgbsl(bangid2)[0];
|
||
// let sb2 = this.is_sb(bangid1, bangid2)[0];
|
||
// let sb1 = this.is_sb(bangid2, bangid1)[0];
|
||
|
||
// if (sb2 < bs1 && sb1 < bs2)
|
||
// {
|
||
// return true;
|
||
// }
|
||
// else
|
||
// {
|
||
// return false;
|
||
// }
|
||
|
||
};
|
||
|
||
//检测所有会让其它板少条且最小的的板
|
||
JS_sb_minmz = (): number =>
|
||
{
|
||
let Bangidzh = this.Find_BS();
|
||
if (Bangidzh[0] != 0)
|
||
{
|
||
let tempbang: YH_bang[] = [];
|
||
for (let m = 0; m < Bangidzh.length; m++)
|
||
{
|
||
tempbang.push(this.xbang[this.getID(Bangidzh[m])]);
|
||
}
|
||
if (tempbang.length > 0)
|
||
{
|
||
tempbang.sort((a, b) => a.pbg * a.pbk - b.pbg * b.pbk);
|
||
return tempbang[0].bangid;
|
||
}
|
||
else if (tempbang.length == 1)
|
||
{
|
||
return tempbang[0].bangid;
|
||
}
|
||
else
|
||
{
|
||
return -1;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
return -1;
|
||
}
|
||
};
|
||
//合并所有的板
|
||
HB_b = () =>
|
||
{
|
||
let jshb_lr: boolean = true;
|
||
let jshb_td: boolean = true;
|
||
let jshb: boolean;
|
||
for (let i = 0; i < this.xbang.length; i++)
|
||
{
|
||
if (this.xbang[i].ishb == false) { jshb = true; } else { jshb = false; }
|
||
while (jshb == true)
|
||
{
|
||
if (this.xbang[i].pbg > this.xbang[i].pbk && this.xbang[i].pbk > 100) //左右
|
||
{
|
||
jshb_lr = this.HB_LR(this.xbang[i].bangid, false);
|
||
}
|
||
else
|
||
{
|
||
jshb_lr = false;
|
||
}
|
||
|
||
if ((this.xbang[i].pbg < this.xbang[i].pbk && this.xbang[i].pbg > 100)) //上下合并
|
||
{
|
||
jshb_td = this.HB_TD(this.xbang[i].bangid, false);
|
||
}
|
||
else
|
||
{
|
||
jshb_td = false;
|
||
}
|
||
if (jshb_lr == true || jshb_td == true)
|
||
{
|
||
jshb = true;
|
||
}
|
||
else if (jshb_lr == false || jshb_td == false)
|
||
{
|
||
if ((this.xbang[i].pbg > 100 && this.xbang[i].pbk > 100)) //上下合并
|
||
{
|
||
jshb_lr = this.HB_LR(this.xbang[i].bangid, false);
|
||
jshb_td = this.HB_TD(this.xbang[i].bangid, false);
|
||
if (jshb_lr == true || jshb_td == true) { jshb = true; } else { jshb = false; }
|
||
}
|
||
else
|
||
{
|
||
jshb = false;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
jshb = true;
|
||
}
|
||
}
|
||
if (this.HB_bang.length > 0)
|
||
{
|
||
this.HB.push(this.HB_bang);
|
||
this.HB_bang = [];
|
||
}
|
||
}
|
||
};
|
||
|
||
//合并指定的板 第一步
|
||
HB_Max_bang = (Bangid: number) =>
|
||
{
|
||
if (Bangid > 0)
|
||
{
|
||
let jshb_lr: boolean = true;
|
||
let jshb_td: boolean = true;
|
||
let jshb: boolean;
|
||
let bangid = this.getID(Bangid);
|
||
if (this.xbang[bangid].ishb == false) { jshb = true; } else { jshb = false; }
|
||
while (jshb == true)
|
||
{
|
||
if (this.xbang[bangid].pbg > this.xbang[bangid].pbk && this.xbang[bangid].pbk > 100) //左右
|
||
{
|
||
jshb_lr = this.HB_LR(this.xbang[bangid].bangid, false);
|
||
}
|
||
else
|
||
{
|
||
jshb_lr = false;
|
||
}
|
||
|
||
if ((this.xbang[bangid].pbg < this.xbang[bangid].pbk && this.xbang[bangid].pbg > 100)) //上下合并
|
||
{
|
||
jshb_td = this.HB_TD(this.xbang[bangid].bangid, false);
|
||
}
|
||
else
|
||
{
|
||
jshb_td = false;
|
||
}
|
||
if (jshb_lr == true || jshb_td == true)
|
||
{
|
||
jshb = true;
|
||
}
|
||
else if (jshb_lr == false || jshb_td == false)
|
||
{
|
||
if ((this.xbang[bangid].pbg > 100 && this.xbang[bangid].pbk > 100)) //上下合并
|
||
{
|
||
jshb_lr = this.HB_LR(this.xbang[bangid].bangid, false);
|
||
jshb_td = this.HB_TD(this.xbang[bangid].bangid, false);
|
||
if (jshb_lr == true || jshb_td == true) { jshb = true; } else { jshb = false; }
|
||
}
|
||
else
|
||
{
|
||
jshb = false;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
jshb = true;
|
||
}
|
||
}
|
||
if (this.HB_bang.length > 0)
|
||
{
|
||
this.HB.push(this.HB_bang);
|
||
this.HB_bang = [];
|
||
}
|
||
else
|
||
{
|
||
this.HB.push([Bangid]);
|
||
this.xbang[bangid].ishb = true;
|
||
}
|
||
}
|
||
};
|
||
|
||
|
||
//合并上面的大板 cd为共边长度
|
||
HB_top = (bangid: number, cd: number) =>
|
||
{
|
||
let hbbang: number[] = [];
|
||
let fid: number = bangid;
|
||
while (fid > -1)
|
||
{
|
||
fid = this.F_Top_Big(fid, cd);
|
||
if (fid > -1)
|
||
{
|
||
this.xbang[this.getID(fid)].ishb = true;
|
||
hbbang.push(fid);
|
||
//this.printstr(fid, 1, "大合", -30, 80, 50);
|
||
}
|
||
}
|
||
if (hbbang.length > 0) { this.HB.push(hbbang); }
|
||
};
|
||
//合并下面的大板 cd为共边长度
|
||
HB_down = (bangid: number, cd: number) =>
|
||
{
|
||
let hbbang: number[] = [];
|
||
let fid: number = bangid;
|
||
while (fid > -1)
|
||
{
|
||
fid = this.F_Down_Big(fid, cd);
|
||
if (fid > -1)
|
||
{
|
||
this.xbang[this.getID(fid)].ishb = true;
|
||
hbbang.push(fid);
|
||
// this.printstr(fid, 1, "大合", 10, 80, 50);
|
||
}
|
||
}
|
||
if (hbbang.length > 0) { this.HB.push(hbbang); }
|
||
};
|
||
|
||
//寻找最后一块要切割的板
|
||
F_last_mz = (jlID: number): number =>
|
||
{
|
||
let bangid: number;
|
||
let temp: number[];
|
||
let index: number = 1;
|
||
let lastId: number;
|
||
if (jlID == 0) { lastId = this.F_minMZ(); } else { lastId = jlID; }
|
||
while (true)
|
||
{
|
||
if (lastId == -1) { break; }
|
||
bangid = this.JS_sb_Bxl(lastId); //检测所有会让其它板少条且有两块或者多块边相邻的板
|
||
if (bangid > -1)
|
||
{ this.add_last(bangid, index); index++; lastId = bangid; }
|
||
else
|
||
{
|
||
bangid = this.JS_sb_minmz(); //检测所有会让其它板少条且最小的的板
|
||
if (bangid > -1)
|
||
{ this.add_last(bangid, index); index++; lastId = bangid; }
|
||
else
|
||
{
|
||
if (lastId == -1) { break; }
|
||
bangid = this.F_minJL(lastId);
|
||
if (bangid > -1) { this.add_last(bangid, index); index++; lastId = bangid; }
|
||
else
|
||
{
|
||
bangid = this.F_minMZ(); //找到面积最小的板
|
||
this.add_last(bangid, index);
|
||
index++;
|
||
lastId = bangid;
|
||
}
|
||
}
|
||
}
|
||
// bangid = this.F_minJL(bangid);
|
||
//if (bangid > -1) { this.add_last(bangid, index); index++; }
|
||
|
||
temp = this.Find_BS();
|
||
|
||
if (temp[0] == 0)
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
return index;
|
||
|
||
};
|
||
|
||
|
||
//寻找最后一块要切割的板
|
||
F_last_jl = (jlID: number): number =>
|
||
{
|
||
let bangid: number;
|
||
let temp: number[];
|
||
let index: number = 1;
|
||
let lastId: number;
|
||
if (jlID == 0) { lastId = this.F_minMZ(); } else { lastId = jlID; }
|
||
let tempend: boolean = false;
|
||
while (true)
|
||
{
|
||
if (lastId == -1) { break; }
|
||
bangid = this.JS_sb_Bxl(lastId); //检测所有会让其它板少条且有两块或者多块边相邻的板
|
||
if (bangid > -1)
|
||
{ this.add_last(bangid, index); index++; lastId = bangid; }
|
||
else
|
||
{
|
||
if (lastId == -1) { break; }
|
||
bangid = this.F_minJL(lastId);
|
||
if (bangid > -1)
|
||
{ this.add_last(bangid, index); index++; lastId = bangid; }
|
||
else
|
||
{
|
||
//bangid = this.F_minMZ(); //找到面积最小的板
|
||
// if (lastId == -1) { break; }
|
||
// bangid = this.F_minJL(lastId);
|
||
bangid = this.JS_sb_minmz(); //检测所有会让其它板少条且最小的的板
|
||
|
||
if (bangid > -1) { this.add_last(bangid, index); index++; lastId = bangid; }
|
||
else
|
||
{
|
||
bangid = this.F_minMZ(); //找到面积最小的板
|
||
this.add_last(bangid, index);
|
||
index++;
|
||
lastId = bangid;
|
||
}
|
||
}
|
||
}
|
||
// bangid = this.F_minJL(bangid);
|
||
//if (bangid > -1) { this.add_last(bangid, index); index++; }
|
||
|
||
temp = this.Find_BS();
|
||
|
||
if (temp[0] == 0)
|
||
{
|
||
break;
|
||
}
|
||
|
||
}
|
||
return index;
|
||
|
||
};
|
||
|
||
//打印并添加最后一块
|
||
add_last = (bangid: number, index: number) =>
|
||
{
|
||
let tempx: number;
|
||
//if (index > 9) { tempx = 27; } else { tempx = 10; } 这两行用于测试打印
|
||
//this.printstr(bangid, 1, index.toString(), this.xbang[this.getID(bangid)].pbk / 2 - tempx, this.xbang[this.getID(bangid)].pbg / 2 - 20, 50);
|
||
this.SCid.push(bangid);
|
||
this.xbang[this.getID(bangid)].isqg = true;
|
||
let tempid = this.xbang[this.getID(bangid)].grid;
|
||
if (this.xbang[this.getID(bangid)].grid > -1)
|
||
{
|
||
let tempin = this.xbang[this.getID(tempid)].gr.findIndex((n) => n == bangid);
|
||
if (tempin > -1)
|
||
{
|
||
this.xbang[this.getID(tempid)].gr.splice(tempin, 1);
|
||
if (this.xbang[this.getID(tempid)].gr.length == 0) { this.xbang[this.getID(tempid)].isgr = false; }
|
||
}
|
||
}
|
||
};
|
||
|
||
//找到面积最小的板
|
||
F_minMZ = (): number =>
|
||
{
|
||
let jhb = this.Find_BS();
|
||
if (jhb[0] != 0)
|
||
{
|
||
let tempBang: YH_bang[] = [];
|
||
if (jhb.length == 1)
|
||
{
|
||
return jhb[0];
|
||
}
|
||
else
|
||
{
|
||
for (let i = 0; i < jhb.length; i++)
|
||
{
|
||
tempBang.push(this.xbang[this.getID(jhb[i])]);
|
||
}
|
||
tempBang = tempBang.sort((a, b) =>
|
||
{
|
||
if (a.pbg * a.pbk == b.pbg * b.pbk)
|
||
{
|
||
return Math.hypot(this.B_k - a.x - a.pbk / 2, this.B_g - a.y - a.pbg / 2) - Math.hypot(this.B_k - b.x - b.pbk / 2, this.B_g - b.y - b.pbg / 2);
|
||
}
|
||
else
|
||
{
|
||
return a.pbg * a.pbk - b.pbg * b.pbk ? -1 : 1;
|
||
}
|
||
});
|
||
|
||
return tempBang[0].bangid;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
return -1;
|
||
}
|
||
};
|
||
|
||
//按位置最近排序
|
||
F_minJL = (bangid: number): number =>
|
||
{
|
||
let jhb = this.Find_BS();
|
||
if (jhb.length[0] != 0)
|
||
{
|
||
let tempBang: YH_bang[] = [];
|
||
if (jhb.length > 0)
|
||
{
|
||
for (let i = 0; i < jhb.length; i++)
|
||
{
|
||
tempBang.push(this.xbang[this.getID(jhb[i])]);
|
||
}
|
||
let wzx = this.xbang[this.getID(bangid)].x + this.xbang[this.getID(bangid)].pbk / 2;
|
||
let wzy = this.xbang[this.getID(bangid)].y + this.xbang[this.getID(bangid)].pbg / 2;
|
||
tempBang.sort((a, b) => a.pbk * a.pbg - b.pbk * b.pbg);
|
||
if (tempBang[tempBang.length - 1].pbg * tempBang[tempBang.length - 1].pbk / 1000000 - tempBang[0].pbg * tempBang[0].pbk / 1000000 > 0.2)
|
||
{
|
||
return tempBang[0].bangid;
|
||
}
|
||
else
|
||
{
|
||
tempBang.sort((a, b) => Math.hypot(wzx - a.x - a.pbk / 2, wzy - a.y - a.pbg / 2) - Math.hypot(wzx - b.x - b.pbk / 2, wzy - b.y - b.pbg / 2));
|
||
return tempBang[0].bangid;
|
||
}
|
||
}
|
||
else if (jhb.length == 1)
|
||
{
|
||
return jhb[0];
|
||
}
|
||
else
|
||
{
|
||
return -1;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
return -1;
|
||
}
|
||
};
|
||
//检测所有会让其它板少条且有两块或者多块边相邻的板
|
||
JS_sb_Bxl = (bangid: number): number =>
|
||
{
|
||
let Bangidzh = this.Find_BS();
|
||
if (Bangidzh[0] != 0)
|
||
{
|
||
let tempbang: YH_bang[] = [];
|
||
let tempxj: YH_bang[] = [];
|
||
let temp: YH_bang;
|
||
for (let m = 0; m < Bangidzh.length; m++)
|
||
{
|
||
for (let n = 0; n < Bangidzh.length; n++)
|
||
{
|
||
if (m != n)
|
||
{
|
||
if (this.Jcsb(Bangidzh[m], Bangidzh[n]) == true)
|
||
{
|
||
tempbang.push(this.xbang[this.getID(Bangidzh[m])]);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (tempbang.length == 1)
|
||
{
|
||
return tempbang[0].bangid;
|
||
}
|
||
else if (tempbang.length == 0)
|
||
{
|
||
return -1;
|
||
}
|
||
else //(tempbang.length > 1);
|
||
{
|
||
let wzx = this.xbang[this.getID(bangid)].x + this.xbang[this.getID(bangid)].pbk / 2;
|
||
let wzy = this.xbang[this.getID(bangid)].y + this.xbang[this.getID(bangid)].pbg / 2;
|
||
tempbang.sort((a, b) => Math.hypot(wzx - a.x - a.pbk / 2, wzy - a.y - a.pbg / 2) - Math.hypot(wzx - b.x - b.pbk / 2, wzy - b.y - b.pbg / 2));
|
||
return tempbang[0].bangid;
|
||
|
||
}
|
||
}
|
||
else
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
};
|
||
|
||
//用于计算下刀顺序
|
||
XDscjs = () =>
|
||
{
|
||
let bangid = this.MaxMZ(0.05);
|
||
this.HB_Max_bang(bangid);
|
||
this.HB_top(bangid, 200);
|
||
this.HB_down(bangid, 200);
|
||
this.F_GL_LR();
|
||
this.F_GL_TD();
|
||
this.Is_big_gr();
|
||
this.F_GL_JJB();
|
||
|
||
let index: number;
|
||
|
||
if (this.jl_mz == 1)
|
||
{
|
||
index = this.F_last_jl(0);
|
||
} else
|
||
{
|
||
index = this.F_last_mz(0);
|
||
}
|
||
this.printHBCS(index);
|
||
|
||
|
||
};
|
||
printHBCS = (index: number) =>
|
||
{
|
||
for (let m = this.HB.length - 1; m >= 0; m--)
|
||
{
|
||
for (let n = this.HB[m].length - 1; n >= 0; n--)
|
||
{
|
||
//this.printstr(this.HB[m][n], 1, index.toString(), this.Bakbang[this.getID_Bkb(this.HB[m][n])].pbk / 2, this.Bakbang[this.getID_Bkb(this.HB[m][n])].pbg / 2, 50);
|
||
this.SCid.push(this.HB[m][n]);
|
||
index++;
|
||
};
|
||
}
|
||
};
|
||
};
|
||
|
||
|
||
|
||
function equaln(v1: number, v2: number, fuzz = 1e-5)
|
||
{
|
||
return Math.abs(v1 - v2) <= fuzz;
|
||
}
|
||
|
||
|
||
|
||
|
||
export interface YH_bang
|
||
{
|
||
bangid: number;
|
||
line: number ;
|
||
x: number;
|
||
y: number;
|
||
pbg: number;
|
||
pbk: number;
|
||
ishb?: boolean;//是否参与合并的板
|
||
hb?: number[]; //合在并的板
|
||
isgr?: boolean; //是否关连
|
||
gr?: number[];//关联的板的集合
|
||
grid: number; //跟别的板关联的ID
|
||
isbig?: boolean;//是否为合并的大板
|
||
isqg?: boolean;//是否被切掉的板
|
||
|
||
}
|