Files
cut-abstractions/tests/dev1/dataHandle/common/cutorder/CutPointHelper.ts

441 lines
15 KiB
TypeScript
Raw Normal View History

2025-07-22 18:22:31 +08:00
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;
}
}