import { ArrayExt } from "../../common/base/ArrayExt.js"; import { Curve2d } from "../../common/base/CAD.js"; import { BlockBorderPoint, PlaceBlock, PlaceBoard, PlaceMaterial } from "../../confClass.js"; import { BlockHelper } from "../LayoutEngine/BlockHelper.js"; import { BlockPlus } from "../LayoutEngine/BlockPlus.js"; import { Point } from "../Vector2.js"; //下刀点的逻辑类 export class CutPointHelper { /** 手动 设置下刀点 * 获得离鼠标最近的顶角 距离都大于50 则返回null */ static getCutPointWithClick(block: PlaceBlock, mousePos: Point): BlockBorderPoint | null { let curves = BlockPlus.getBorder(block); let dis = Number.MAX_VALUE; let point: Point; let index = -1; for (let i = 0; i < curves.length; i++) { let line = curves[i]; let d = Math.pow(line.StartPoint.m_X + block.placeX - mousePos.x, 2) + Math.pow(line.StartPoint.m_Y + block.placeY - mousePos.y, 2); if (d < dis) { point = new Point(line.StartPoint.m_X, line.StartPoint.m_Y); dis = d; index = i; } } if (index == -1) return null; //距离太远,不选择 let apexId = BlockHelper.getApexAngleNumFromBlock(block, point); block.cutPointId = index; return new BlockBorderPoint(block, point.x, point.y, index, apexId); } /** 计算所有板材的下刀点 */ static async autoFindAllCutPoint(pmList: PlaceMaterial[]) { for (const pm of pmList) { for (const pb of pm.boardList) { await this.autoFindCutPoint(pm, pb) } } } //以下是自动设置 下刀点 static gap = 7; static cutedSpace = 100; //走刀100内 不能算靠板 static lines_V: any[] = []; //垂直线, x ,y1,y2 static lines_H: any[] = []; //水平线 x1,x2, y; /** 计算当前板材的下刀点 * 若传入 block 则只计算block的下刀点 */ static autoFindCutPoint(pm: PlaceMaterial, pb: PlaceBoard, block: PlaceBlock | null = null) { if (pb.blockList.length == 0) return; //初始化 this.gap = pm.diameter + pm.cutKnifeGap; this.lines_H = []; //开料水平线 this.lines_V = []; //开料垂直线 //大板外轮廓 边缘线 if (pb.points.length == 0) { let p0 = { x: 0, y: 0 }; let p1 = { x: pb.width, y: 0 }; let p2 = { x: pb.width, y: pb.length }; let p3 = { x: 0, y: pb.length }; this.pushLine(p0, p1); this.pushLine(p1, p2); this.pushLine(p2, p3); this.pushLine(p3, p0); } else { for (let i = 0; i < pb.points.length; i++) { let j = i + 1; if (j == pb.points.length) j = 0; this.pushLine(pb.points[i], pb.points[j]); } } //有板的时候,除了该板计算,其他的板都不计算下刀点 let hasBlock = (block != null); let blocks = ArrayExt.where(pb.blockList, t => t.cutOrder > 0, t => t.cutOrder); for (let b of blocks) { let notNeedFind = hasBlock && b.blockId == block?.blockId; CutPointHelper.findCutPoint(b, !notNeedFind); } } /**计算下刀点 */ static findCutPoint(block: PlaceBlock, needFind = true) { let list = BlockPlus.getBorder(block); //计算没边的靠板情况,并自动生成 铣板走线 数据 let borders_cuting: any[] = []; for (let i = 0; i < list.length; i++) { let rt = this.getUnCutedLength(block, list, i); borders_cuting.push([i, rt[0], rt[1]]); } if (needFind == false) return; //不计算下刀点 //计算最优下刀点 let unCutedlength = 0; let unCutedSize = 0; let cutPointIndex = -1; for (let i = 0; i < borders_cuting.length; i++) { let data = borders_cuting[i]; let index = data[0]; let len = data[1]; let size = data[2]; if (isBest(len, size)) { cutPointIndex = index; unCutedlength = len; unCutedSize = size; } } if (cutPointIndex >= list.length) cutPointIndex -= list.length; block.cutPointId = cutPointIndex + 1; //四周都没有靠的 if (cutPointIndex == -1) { this.getCutPointWithClick(block, new Point(block.placeWidth, block.placeLength)); } function isBest(len1, size1) //判断那条边 更优 { if (len1 == 0) return false; //没有考的 let dis_avg = size1 / len1; if (dis_avg < 50) return false; //跟最近的 平均距离 < 50 ,当作没有考的 if (cutPointIndex == -1) return true; //return len1 > unCutedlength; if (len1 > 150 && unCutedlength < 150) return true; if (len1 > unCutedlength * 2) return true; if (size1 > unCutedSize * 1.2) return true; //未切面积 相差很大. 取 if (size1 < unCutedSize * 0.8) return false; //小于 以获得的 边 , 不取 if (len1 > unCutedlength) return true; //面积相差无几, 取边长的 return false; } } /**获取未切边长度 */ private static getUnCutedLength(block: PlaceBlock, curs: Curve2d[], i): [number, number] { let cur = curs[i]; let p1 = { x: block.placeX + cur.StartPoint.m_X, y: block.placeY + cur.StartPoint.m_Y }; let p2 = { x: block.placeX + cur.EndPoint.m_X, y: block.placeY + cur.EndPoint.m_Y }; let length = Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y); //切边总长度 let cutedLength = 0; let cutedSize = 0; let dat_H; let dat_V; let isSP = this.qual(p1.y, p2.y); let isCZ = this.qual(p1.x, p2.x); if (isSP) //水平 { dat_H = this.getcutedLength_h(p1, p2); } else if (isCZ) //垂直 { dat_V = this.getcutedLength_v(p1, p2); } else if (p2.y > p1.y) { if (p2.x > p1.x) //右上 { let pc = { x: p2.x, y: p1.y }; dat_H = this.getcutedLength_h(p1, pc); dat_V = this.getcutedLength_v(pc, p1); } else //左上 { let pc = { x: p1.x, y: p2.y }; dat_V = this.getcutedLength_v(p1, pc); dat_H = this.getcutedLength_h(pc, p2); } } else { if (p2.x > p1.x) //右下 { let pc = { x: p1.x, y: p2.y }; dat_V = this.getcutedLength_v(p1, pc); dat_H = this.getcutedLength_h(p1, pc); } else //左下 { let pc = { x: p2.x, y: p1.y }; dat_H = this.getcutedLength_h(p1, pc); dat_V = this.getcutedLength_v(p1, pc); } } if (dat_H) { cutedLength += dat_H[0]; cutedSize += dat_H[4]; this.pushline_H(dat_H[1], dat_H[2], dat_H[3]); } if (dat_V) { cutedLength += dat_V[0]; cutedSize += dat_V[4]; this.pushline_V(dat_V[1], dat_V[2], dat_V[3]); } let unCutedLength = length - cutedLength; if (unCutedLength < 0) unCutedLength = 0; if (unCutedLength > 0 && block.isUnRegular) //避免异形板、格子抽、齿的边被选出来 { //边缘线不计算 let isborder = isSP && (this.qual(cur.StartPoint.m_Y, 0) || this.qual(cur.StartPoint.m_Y, block.placeLength)); if (isborder == false) { isborder = isCZ && (this.qual(cur.StartPoint.m_X, 0) || this.qual(cur.StartPoint.m_X, block.placeWidth)); } if (isborder == false) { for (let j = 0; j < curs.length; j++) { if (i == j) continue; let other = curs[j]; if (isSP && this.qual(other.StartPoint.m_Y, other.EndPoint.m_Y)) //水平,line 在板内 { if (this.qual(other.StartPoint.m_Y, 0)) continue; //边缘线,不计算 if (this.qual(other.StartPoint.m_Y, block.placeLength)) continue; if (this.qual(cur.StartPoint.m_Y, other.StartPoint.m_Y, 100)) { unCutedLength = 0; break; } } else { if (isCZ && this.qual(other.StartPoint.m_X, other.EndPoint.m_X)) { if (this.qual(other.StartPoint.m_X, 0)) continue; if (this.qual(other.StartPoint.m_X, block.placeWidth)) continue; if (this.qual(cur.StartPoint.m_X, other.StartPoint.m_X, 100)) { unCutedLength = 0; break; } } } } } } return [unCutedLength, cutedSize]; } /**获取水平开料边长度 */ private static getcutedLength_h(p1, p2): [number, number, number, number, number] //cutedLength,x1,x2,y { //水平线 let x1; let x2; let y = p1.y; //切片法 let cell = 5; let cutedLength = 0; let cutedSize = 0; if (p2.x > p1.x) // 向右,往下面100内找有没有切割的走刀 { x1 = p1.x; x2 = p2.x; let cutedLines = this.lines_H.filter(t => t.y < y && t.x1 < x2 && t.x2 > x1); //向右,下面找 for (let pos = x1; pos < x2 + 5; pos += cell) { let lines = ArrayExt.where(cutedLines, t => t.x1 <= pos && t.x2 > pos, t => -t.y); //按y降序排序 ,找最高的 if (lines.length > 0) { let line = lines[0]; let disY = Math.abs(line.y - y); if (disY < 100) cutedLength = cutedLength + cell; cutedSize += disY * cell; } } } else //往左 { x1 = p2.x; x2 = p1.x; let cutedLines = this.lines_H.filter(t => t.y > y && t.x1 < x2 && t.x2 > x1); //向左,上面找 for (let pos = x1; pos < x2 + 5; pos += cell) { let lines = ArrayExt.where(cutedLines, t => t.x1 <= pos && t.x2 > pos, t => t.y); //按y上线排序 ,找最底的 if (lines.length > 0) { let line = lines[0]; let disY = Math.abs(line.y - y); if (disY < 100) cutedLength = cutedLength + cell; cutedSize += disY * cell; } } } return [cutedLength, x1, x2, p1.y, cutedSize]; } /**获取竖直方向开料边长度 */ private static getcutedLength_v(p1, p2): [number, number, number, number, number] //cutedLength,x,y1,y2 { // let x = p1.x; // let x1; // let x2; // let y1; // let y2; // if (p2.y > p1.y) // 向上,往右面100内找有没有切割的走刀 // { // y1 = p1.y; // y2 = p2.y; // x1 = p1.x; // x2 = p1.x + this.cutedSpace;;; // } // else //往下 // { // y1 = p2.y; // y2 = p1.y; // x1 = p1.x - this.cutedSpace; // x2 = p1.x; // } // let cutedLines = this.lines_V.filter(t => t.x > x1 && t.x < x2 && t.y1 < y2 && t.y2 > y1); // //切片法 // let cell = 5; // let cutedLength = 0; // let cutedSize = 0; // if (cutedLines.length > 0) // { // for (let y = y1; y < y2 + 5; y += cell) // { // let line = cutedLines.find(t => t.y1 <= y && t.y2 > y); // if (line) // { // cutedLength += cell; // cutedSize += Math.abs(line.x - p1.x) * cell; // } // } // } // return [cutedLength, p1.x, y1, y2, cutedSize]; let x = p1.x; let y1; let y2; let cell = 5; let cutedLength = 0; let cutedSize = 0; if (p2.y > p1.y) // 向上,往右面100内找有没有切割的走刀 { y1 = p1.y; y2 = p2.y; let cutedLines = this.lines_V.filter(t => t.x > x && t.y1 < y2 && t.y2 > y1); //向上,右面找 for (let y = y1; y < y2 + 5; y += cell) { let lines = ArrayExt.where(cutedLines, t => t.y1 <= y && t.y2 > y, t => t.x); if (lines.length > 0) { let line = lines[0]; let dis = Math.abs(line.x - x); if (dis < 100) cutedLength = cutedLength + cell; cutedSize += dis * cell; } } } else //往下 { y1 = p2.y; y2 = p1.y; let cutedLines = this.lines_V.filter(t => t.x < x && t.y1 < y2 && t.y2 > y1); //向下,左面找 for (let y = y1; y < y2 + 5; y += cell) { let lines = ArrayExt.where(cutedLines, t => t.y1 <= y && t.y2 > y, t => -t.x); if (lines.length > 0) { let line = lines[0]; let dis = Math.abs(line.x - x); if (dis < 100) cutedLength = cutedLength + cell; cutedSize += dis * cell; } } } return [cutedLength, p1.x, y1, y2, cutedSize]; } /**保存刀路 */ static pushLine(p1, p2) { if (this.qual(p1.y, p2.y)) //水平 { this.pushline_H(p1.x, p2.x, p1.y); } else if (this.qual(p1.x, p2.y)) //垂直 { this.pushline_V(p1.x, p1.y, p2.y); } else if (p2.y > p1.y) { if (p2.x > p1.x) //右上 { this.pushline_H(p1.x, p2.x, p1.y); this.pushline_V(p2.x, p1.y, p2.y); } else //左上 { this.pushline_V(p1.x, p1.y, p2.y); this.pushline_H(p2.x, p1.x, p2.y); } } else { if (p2.x > p1.x) //右下 { this.pushline_V(p1.x, p1.y, p2.y); this.pushline_H(p1.x, p2.x, p2.y); } else //左下 { this.pushline_H(p2.x, p1.x, p1.y); this.pushline_V(p2.x, p1.y, p2.y); } } } /**保存水平刀路 */ private static pushline_H(x1, x2, y) { this.lines_H.push({ x1: Math.min(x1, x2), x2: Math.max(x1, x2), y: y }); } /**保存竖直刀路 */ private static pushline_V(x, y1, y2) { this.lines_V.push({ x: x, y1: Math.min(y1, y2), y2: Math.max(y1, y2) }); } /**判断是否相等 */ static qual(x, y, off = 0.005): boolean { return Math.abs(x - y) < off; } }