feat:提交
This commit is contained in:
387
tests/dev1/dataHandle/common/cutorder/CutOrder.ts
Normal file
387
tests/dev1/dataHandle/common/cutorder/CutOrder.ts
Normal file
@@ -0,0 +1,387 @@
|
||||
|
||||
import { Point2d } from '../../common/base/CAD.js';
|
||||
import { ArrayExt } from '../../common/base/ArrayExt.js';
|
||||
import { BlockRegion, PlaceBlock, PlaceBoard, PlaceMaterial } from '../../confClass.js';
|
||||
import { Point } from '../Vector2.js';
|
||||
import { BlockPlus } from '../LayoutEngine/BlockPlus.js';
|
||||
import {
|
||||
KLSC, YH_bang
|
||||
|
||||
} from '../../confClass.js';
|
||||
import { PlacePosition } from '../PlacePosition.js';
|
||||
import { BlockHelper } from '../LayoutEngine/BlockHelper.js';
|
||||
/** 开料顺序类 */
|
||||
export class CutOrder {
|
||||
/** 开料顺序 */
|
||||
static autoSetCutOrder(materialList: PlaceMaterial[], config, useNewSort = false) {
|
||||
// let order = PlaceStore.order;
|
||||
|
||||
// console.log(order.materialList);
|
||||
let newMaterialList = [...materialList]
|
||||
for (let pm of newMaterialList) {
|
||||
for (let pb of pm.boardList) {
|
||||
this.autoCalcCutOrder(pm, pb, config, useNewSort);
|
||||
}
|
||||
}
|
||||
return newMaterialList
|
||||
}
|
||||
/** 自动计算开料顺序 useNewSort是否使用新开料顺序算法*/
|
||||
static autoCalcCutOrder(pm: PlaceMaterial, pb: PlaceBoard, config, useNewSort = false) {
|
||||
if (pb.isLocked) return;
|
||||
let blocks = pb.blockList;
|
||||
|
||||
if (blocks.length == 0) return;
|
||||
if (blocks.length == 1) {
|
||||
blocks[0].cutOrder = 1;
|
||||
}
|
||||
else {
|
||||
let isUseNewSort = useNewSort; //使用新开料顺序算法
|
||||
if (isUseNewSort && checkBoardCross()) isUseNewSort = false; //异形穿插的大板使用旧的开料顺序算法
|
||||
if (isUseNewSort) {
|
||||
this.autoSortBlockNew(pm, pb);
|
||||
}
|
||||
else {
|
||||
this.autoSortBlock(pm, pb, config);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('开料顺序', pm, pb, pb.blockList.map(e => e.cutOrder));
|
||||
// //自动设置下刀点
|
||||
// CutPointHelper.autoFindCutPoint(pm, pb);
|
||||
|
||||
/** 判断大板是否有交叉的大板(包括、包含) */
|
||||
function checkBoardCross() {
|
||||
for (let i = 0; i < pb.blockList.length; i++) {
|
||||
for (let j = i + 1; j < pb.blockList.length; j++) {
|
||||
if (checkCross(pb.blockList[i], pb.blockList[j])) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkCross(b1: PlaceBlock, b2: PlaceBlock): boolean {
|
||||
let c1 = { x: b1.placeX + b1.placeWidth / 2, y: b1.placeY + b1.placeLength / 2 };
|
||||
let c2 = { x: b2.placeX + b2.placeWidth / 2, y: b2.placeY + b2.placeLength / 2 };
|
||||
|
||||
return Math.abs(c1.x - c2.x) < (b1.placeWidth / 2 + b2.placeWidth / 2) && Math.abs(c1.y - c2.y) < (b1.placeLength / 2 + b2.placeLength / 2);
|
||||
}
|
||||
|
||||
return pb
|
||||
}
|
||||
|
||||
|
||||
/** 新开料顺序算法 */
|
||||
static autoSortBlockNew(pm: PlaceMaterial, pb: PlaceBoard) {
|
||||
let selectBs = pb.blockList;
|
||||
let beginId = 0;
|
||||
const has0 = pb.blockList.filter(t => t.cutOrder == 0);
|
||||
const has1 = pb.blockList.filter(t => t.cutOrder > 0);
|
||||
const has2 = pb.blockList.filter(t => t.cutOrder < 0);
|
||||
//有手动指定开料顺序的
|
||||
if (has0.length > 0 && (has1.length + has2.length) > 0) {
|
||||
selectBs = has0;
|
||||
if (has1.length > 0) //开头的
|
||||
{
|
||||
const bs = has1.sort((a, b) => a.cutOrder - b.cutOrder);
|
||||
for (const b of bs) {
|
||||
beginId++;
|
||||
b.cutOrder = beginId;
|
||||
}
|
||||
}
|
||||
if (has2.length > 0) //结尾的
|
||||
{
|
||||
const bs = has2.sort((a, b) => a.cutOrder - b.cutOrder);
|
||||
let endId = has0.length + has1.length;
|
||||
for (const b of bs) {
|
||||
endId++;
|
||||
b.cutOrder = endId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let bangs: YH_bang[] = [];
|
||||
let blocks = new Array();
|
||||
for (let i = 0; i < selectBs.length; i++) {
|
||||
let block = selectBs[i];
|
||||
let bangid = i + 1;
|
||||
let line = 0;
|
||||
let x = block.placeX;
|
||||
let y = block.placeY;
|
||||
let pbg = block.placeLength;
|
||||
let pbk = block.placeWidth;
|
||||
let ishb = false; //是否参与合并的板
|
||||
let isbig = false; //是否为合并的大板;
|
||||
blocks[bangid] = block;
|
||||
|
||||
bangs.push({
|
||||
bangid,
|
||||
line: 0,
|
||||
pbg,
|
||||
pbk,
|
||||
x,
|
||||
y,
|
||||
ishb: false,
|
||||
hb: [],
|
||||
isbig: false,
|
||||
isqg: false,
|
||||
isgr: false,
|
||||
gr: [],
|
||||
grid: -1
|
||||
});
|
||||
}
|
||||
let dt = pm.diameter + pm.cutKnifeGap;
|
||||
let k = pb.width;
|
||||
let g = pb.length;
|
||||
|
||||
let xdsc = new KLSC(bangs, k, g, dt, 0, 0, 1);
|
||||
let rt = xdsc.SCid;
|
||||
// let rt = JSXDSC(bangs, dt, k, g);
|
||||
|
||||
if (rt.length < selectBs.length) return;
|
||||
for (let i = 0; i < rt.length; i++) {
|
||||
let bid = rt[i];
|
||||
beginId++;
|
||||
blocks[bid].cutOrder = beginId;
|
||||
}
|
||||
}
|
||||
|
||||
/** 设置下刀点 */
|
||||
static setCutPoint(block: PlaceBlock, cutRegion: BlockRegion) {
|
||||
block.cutRegion = cutRegion;
|
||||
let x = 0,
|
||||
y = 0;
|
||||
|
||||
if (cutRegion == BlockRegion.RIGHT_BOTTOM)
|
||||
// if (cutRegion == BlockRegion.LEFT_BOTTOM)
|
||||
{
|
||||
x = block.placeWidth;
|
||||
}
|
||||
if (cutRegion == BlockRegion.RIGHT_TOP)
|
||||
// if (cutRegion == BlockRegion.RIGHT_BOTTOM)
|
||||
{
|
||||
x = block.placeWidth;
|
||||
y = block.placeLength;
|
||||
}
|
||||
if (cutRegion == BlockRegion.LEFT_TOP)
|
||||
// if (cutRegion == BlockRegion.RIGHT_TOP)
|
||||
{
|
||||
y = block.placeLength;
|
||||
}
|
||||
|
||||
block.cutPointId = CutOrder.findCutPoint(block, x, y);
|
||||
}
|
||||
|
||||
/**计算下刀点 */
|
||||
private static findCutPoint(block: PlaceBlock, x: number, y: number): number {
|
||||
let list = BlockPlus.getBorder(block);
|
||||
let p = new Point2d(x, y);
|
||||
let mV = Number.MAX_VALUE;
|
||||
let index = 0;
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
let v = p.DistensTo(list[i].StartPoint);
|
||||
if (v < mV) {
|
||||
mV = v;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
/**获得下刀点坐标 */
|
||||
static getCutPointInBloard(block: PlaceBlock): Point {
|
||||
let curves = BlockPlus.getBorder(block);
|
||||
while (block.cutPointId >= curves.length) {
|
||||
block.cutPointId = block.cutPointId - curves.length;
|
||||
}
|
||||
while (block.cutPointId < 0) {
|
||||
block.cutPointId = block.cutPointId + curves.length;
|
||||
}
|
||||
let p = curves[block.cutPointId].StartPoint;
|
||||
//内收 一个刀直径
|
||||
let rx = p.m_X;
|
||||
let ry = p.m_Y;
|
||||
let offv =
|
||||
block.blockDetail.offsetKnifeRadius == 0 ? 6 : block.blockDetail.offsetKnifeRadius * 2;
|
||||
if (p.m_X == 0) rx = offv;
|
||||
if (p.m_X == block.placeWidth) rx = block.placeWidth - offv;
|
||||
if (p.m_Y == 0) ry = offv;
|
||||
if (p.m_Y == block.placeLength) ry = block.placeLength - offv;
|
||||
|
||||
return new Point(block.placeX + rx, block.placeY + ry);
|
||||
}
|
||||
|
||||
//原开料顺序算法--------------------------------------------------------
|
||||
|
||||
//原开料顺序算法
|
||||
static autoSortBlock(pm: PlaceMaterial, pb: PlaceBoard, config: any) {
|
||||
let blocks = pb.blockList;
|
||||
//将小板位置恢复到左下角靠板的状态
|
||||
PlacePosition.resetPlacePosition(pb, config);
|
||||
|
||||
//清除 开料顺序
|
||||
//如果全部都有开料序号,(重新优化,或移动小板等需要清除开料顺序)
|
||||
//手动设置开料顺序一半时,不能把设置的开料顺序清空
|
||||
if (!blocks.some(t => t.cutOrder == 0)) {
|
||||
blocks.forEach(t => (t.cutOrder = 0));
|
||||
}
|
||||
|
||||
/**板板之间距离 */
|
||||
let cutGap = pm.diameter + pm.cutKnifeGap;
|
||||
let sortId = ArrayExt.max(blocks, t => t.cutOrder) + 1;
|
||||
|
||||
//优先排大板内部的小板
|
||||
for (let block of blocks) {
|
||||
if (block.cutOrder != 0) continue;
|
||||
let blocks_innner = BlockHelper.getInnerBlock(block, blocks);
|
||||
if (blocks_innner && blocks_innner.length > 0) {
|
||||
while (true) {
|
||||
let topB = this.findTopBlock(blocks_innner);
|
||||
if (topB == null) break;
|
||||
let coverBlock = CutOrder.findCoverBlock(blocks_innner, topB);
|
||||
coverBlock.cutOrder = sortId++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//优先排四周(50mm)的小板
|
||||
|
||||
//优先排左侧小板
|
||||
this.autoSortBlockLeft(blocks, cutGap);
|
||||
//优先排下侧小板
|
||||
this.autoSortBlockBottom(blocks, cutGap);
|
||||
|
||||
sortId = ArrayExt.max(blocks, t => t.cutOrder, t => true, 0) + 1;
|
||||
|
||||
while (true) {
|
||||
let topB = this.findTopBlock(blocks);
|
||||
if (topB == null) break;
|
||||
let coverBlock = CutOrder.findCoverBlock(blocks, topB);
|
||||
coverBlock.cutOrder = sortId++;
|
||||
CutOrder.setCutPoint(coverBlock, BlockRegion.LEFT_BOTTOM);
|
||||
}
|
||||
if (blocks.some(t => t.cutOrder < 0)) //有手工设置倒数开料的
|
||||
{
|
||||
//将开料顺序为负数的设置成最后
|
||||
for (let b of blocks) {
|
||||
if (b.cutOrder < 0) b.cutOrder = b.cutOrder + blocks.length + 1;
|
||||
}
|
||||
}
|
||||
else //全自动 开料顺序,比较最后2片,倒数第二片是否更优
|
||||
{
|
||||
let lastBlock = blocks.find(t => t.cutOrder == blocks.length);
|
||||
let lastBlock2 = blocks.find(t => t.cutOrder == blocks.length - 1);
|
||||
|
||||
if (lastBlock && lastBlock2) {
|
||||
if (lastBlock.area < 0.3 && lastBlock2.area - 0.1 > lastBlock.area) {
|
||||
lastBlock.cutOrder--;
|
||||
lastBlock2.cutOrder++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//将小板位置 恢复到 系统配置的靠板 状态
|
||||
PlacePosition.resetPlacePosition(pb, config);
|
||||
}
|
||||
|
||||
|
||||
/**手工排序:如果 cutOrder == 0 按当前板顺序,如果 >0 则设置为值,板上比他的大的设置为0 */
|
||||
static resetCutOrder(pb: PlaceBoard, block: PlaceBlock, cutOrder: number = 0) {
|
||||
if (cutOrder > 0) {
|
||||
block.cutOrder = cutOrder;
|
||||
}
|
||||
else {
|
||||
for (let block of pb.blockList) {
|
||||
if (block.cutOrder >= cutOrder) {
|
||||
block.cutOrder = 0;
|
||||
}
|
||||
}
|
||||
block.cutOrder = cutOrder;
|
||||
}
|
||||
}
|
||||
|
||||
/**优先排大板左侧的小板 (细长条) */
|
||||
private static autoSortBlockLeft(blocks: PlaceBlock[], curtGap: number) {
|
||||
// let sysConfig = PlaceStore.sysConfig;
|
||||
let blockList = ArrayExt.orderBy(blocks, t => t.placeX, t => -t.placeY);
|
||||
for (const b of blockList) {
|
||||
// if (b.cutOrder != 0 || b.placeWidth > SysConfig.AutoSortingMinWidth) continue;
|
||||
if (b.cutOrder != 0) continue;
|
||||
|
||||
//查询挡住的板个数 : 在b左边,且b的前 板件之内
|
||||
let count = ArrayExt.count(
|
||||
blockList,
|
||||
t =>
|
||||
t.cutOrder == 0 &&
|
||||
b.placeX > t.placeX + t.placeWidth &&
|
||||
t.placeY < b.placeY + b.placeLength &&
|
||||
t.placeY + t.placeLength > b.placeY
|
||||
);
|
||||
if (count == 0) //判断是否在其他板内部
|
||||
{
|
||||
let count2 = ArrayExt.count(
|
||||
blockList,
|
||||
t =>
|
||||
t.cutOrder == 0 &&
|
||||
b.placeX >= t.placeX && b.placeX < t.placeX + t.placeWidth &&
|
||||
t.placeY > b.placeY && t.placeY < b.placeY + b.placeLength
|
||||
);
|
||||
count += count2;
|
||||
}
|
||||
if (count == 0) {
|
||||
b.cutOrder = ArrayExt.max(blockList, t => t.cutOrder, t => true, 0) + 1;
|
||||
CutOrder.setCutPoint(b, BlockRegion.RIGHT_TOP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**优先排大板下侧的小板 (短粗条) */
|
||||
private static autoSortBlockBottom(blocks: PlaceBlock[], curtGap: number) {
|
||||
// let SysConfig = PlaceStore.sysConfig;
|
||||
//排序,
|
||||
let list = ArrayExt.orderBy(blocks, t => t.placeY, t => -t.placeX);
|
||||
for (const b of list) {
|
||||
// if (b.cutOrder != 0 || b.placeLength > SysConfig.AutoSortingMinWidth) continue;
|
||||
if (b.cutOrder != 0) continue;
|
||||
|
||||
//查询挡住的板个数 : 在b上面边,且b的前 板件之内
|
||||
let count = ArrayExt.count(list, t =>
|
||||
t.cutOrder == 0 &&
|
||||
b.placeY > t.placeY + t.placeLength &&
|
||||
t.placeX < b.placeX + b.placeWidth &&
|
||||
t.placeX + t.placeWidth > b.placeX);
|
||||
if (count == 0) {
|
||||
b.cutOrder = ArrayExt.max(list, t => t.cutOrder, t => true, 0) + 1;
|
||||
CutOrder.setCutPoint(b, BlockRegion.LEFT_TOP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//block列表中找到最远的板
|
||||
static findTopBlock(blocks: PlaceBlock[]): PlaceBlock {
|
||||
return ArrayExt.last(blocks, t => t.cutOrder == 0, t => t.placeY + t.placeLength, t => t.placeX + t.placeWidth);
|
||||
}
|
||||
|
||||
//寻找挡在block之前(x+)的板
|
||||
private static findCoverBlock(blocks: PlaceBlock[], block: PlaceBlock): PlaceBlock {
|
||||
let unSortCount = ArrayExt.count(blocks, t => t.cutOrder == 0);
|
||||
if (unSortCount == 1) return block;
|
||||
let blocks_cover: PlaceBlock[] = [];
|
||||
|
||||
//可以挡住block 的板列表: 在block 右边(posx 大) ,顶点在 block 之间
|
||||
blocks_cover = ArrayExt.where(blocks, t =>
|
||||
t.cutOrder == 0
|
||||
&& t != block
|
||||
&& t.placeX > block.placeX
|
||||
&& t.placeY + t.placeLength > block.placeY);
|
||||
//如果没有挡住的板,则返回最高板
|
||||
if (blocks_cover.length == 0) return block;
|
||||
let nextBlock = ArrayExt.last(blocks_cover, t => true, t => t.placeY + t.placeLength);
|
||||
return CutOrder.findCoverBlock(blocks, nextBlock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
440
tests/dev1/dataHandle/common/cutorder/CutPointHelper.ts
Normal file
440
tests/dev1/dataHandle/common/cutorder/CutPointHelper.ts
Normal file
@@ -0,0 +1,440 @@
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user