commit 6f3a8959dbd1e23243d14a2e415bc677432ddb55 Author: lixiang <504331699@qq.com> Date: Thu Jul 31 17:36:08 2025 +0800 feat:提交 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..55b3403 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.tgz +node_modules/* +*.yaml +dist/* \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..81638bc --- /dev/null +++ b/README.md @@ -0,0 +1,111 @@ +# @mes-processors/libs + +这是一个用于处理MES(制造执行系统)相关工作流的处理器类库。 + +## 安装 + +在内网环境下执行以下脚本进行安装 + +```sh +pnpm add http://gitea.cf/MES-FE/mes-packages/releases/download/0.1/mes-processors-libs-0.1.0.tgz +``` + +> [!CAUTION] +> 在安装库之前,请确认以下信息: +> +> - 该库发布于内网gitea仓库的release中,所以你需要提前在gitea中进行登录,并确保你有该仓库的访问权限。 +> - 库的版本需要手动进行控制,注意上述链接中的版本信息,在安装前需要主动修改版本号,请前往来确认最新版本。 + +## 使用 + +该库提供了MES/iMES公用的处理器,并已配置为导出项,请参考以下Typescript代码进行使用: + +```ts +// 引入矩形优化处理器 +import { RectLayoutProcConfig } from 'cut-abstractions'; +import { RectLayoutProc } from '@mes-processors/libs'; + +// 实例化处理器 +const proc = new RectLayoutProc(); +// 构建上下文f proc.exec>[0] = { + input: testObj, + params: new RectLayoutProcConfig() +}; +// 异步执行 +const ctx: Parameters [!NOTE] +> 发布前记得更改版本号 + +### 约定 + +**目录** + +``` +src +├── modules 项目模块分组 +├── processors 处理器 +└── utils 公用的工具类 +``` + +**导出和打包** + +- 编写的处理器请在`src/index.ts`中进行导出 +- 编写的工具类请在`src/utils/index.ts`中进行导出 +- 在打包时项目仅会对`src/index.ts`进行打包,工具类相关模块不会进行打包 +- 关于打包相关明细请自行查看相关文件 + - [package.json](package.json) + - [vite.config.ts](vite.config.ts) + +> [!WARNING] +> 在该工作区中编写模块时,禁止使用绝对路径进行导入,禁止在`tsconfig.json`或`vite.config.ts`中添加"@"别名,所有导入语句请使用相对路径进行引入,否则会因monorepo内部导入混乱导致模块解析失败。 + +### 测试 + +项目使用[Vitest](http://vitest.dev/)作为单元测试框架,若要对TS文件编写单元测试,请在文件的同目录下创建`<文件名>.test.ts`文件,并遵循Vitest规范编写单元测试。 + +要执行单元测试,请运行下面的命令: +```sh +pnpm test +``` diff --git a/package.json b/package.json new file mode 100644 index 0000000..c52032d --- /dev/null +++ b/package.json @@ -0,0 +1,38 @@ +{ + "name": "@imes-procesor/libs", + "version": "0.1.0", + "description": "", + "type": "module", + "scripts": { + "build": "vite build", + "test": "vitest", + "check": "tsc --noEmit --skipLibCheck -p tsconfig.app.json" + }, + "files": [ + "dist", + "package.json", + "src", + "tsconfig.json", + "tsconfig.app.json", + "tsconfig.node.json" + ], + "exports": { + ".": "./src/index.ts", + "./utils": "./src/utils/index.ts" + }, + "dependencies": { + "cut-abstractions": "http://gitea.cf/MES-FE/cut-abstractions/releases/download/0.2/cut-abstractions-0.2.0.tgz" + }, + "devDependencies": { + "@types/node": "^24.0.10", + "typescript": "~5.8.3", + "vite": "^7.0.0", + "vite-plugin-dts": "^4.5.4", + "vite-plugin-node-polyfills": "^0.24.0", + "vite-plugin-resolve": "^2.5.2", + "vitest": "^3.2.4" + }, + "keywords": [], + "author": "", + "license": "ISC" +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..1cacc38 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,8 @@ +/** + * @package @mes-processors/libs + * @author LX + * @description 工作流处理器类库,在这个文件中使用导出时,不要在路径中使用'@',否则模块无法加载 + */ + +// CutOrder +export * from "./processors/cutOrder/CutOrder"; \ No newline at end of file diff --git a/src/modules/README.md b/src/modules/README.md new file mode 100644 index 0000000..6d39661 --- /dev/null +++ b/src/modules/README.md @@ -0,0 +1,2 @@ +### react-layout +矩形优化算法(陈总新优化) \ No newline at end of file diff --git a/src/modules/cutOrder/ArrayExt.ts b/src/modules/cutOrder/ArrayExt.ts new file mode 100644 index 0000000..7cfba7b --- /dev/null +++ b/src/modules/cutOrder/ArrayExt.ts @@ -0,0 +1,375 @@ +export class List extends Array +{ + /** 返回符合条件的第一个元素 */ + first(fn: (item: Item) => boolean): Item | null + { + if (this.length == 0) + return null + for (const item of this) + { + if (fn(item)) + return item + } + return null + } + + /** 返回符合条件的最后一元素 */ + last(fn: (t: Item) => boolean): Item | null + { + if (this.length == 0) + return null + for (let i = this.length - 1; i >= 0; i--) + { + if (fn(this[i])) + return this[i] + } + return null + } + + /** 最大值 */ + max(fn: (item: Item) => T): T + { + let maxV: T + for (const i of this) + { + let v = fn(i) + if (maxV == null) + { + maxV = fn(i) + } + else + { + if (v > maxV) + { + maxV = v + } + } + } + return maxV + } + + /** 最小值 */ + min(fn: (item: Item) => T): T + { + let minV: T + for (const i of this) + { + let v = fn(i) + if (minV == null) + { + minV = fn(i) + } + else + { + if (v < minV) + { + minV = v + } + } + } + return minV + } + + /** 累加 */ + sum(fn: (item: Item) => number): number + { + let v: number = 0 + for (const t of this) + { + v = v + fn(t) + } + return v + } + + /** 平均值 */ + avg(fn: (item: Item) => number): number + { + if (this.length == 0) + return 0 + let sum = this.sum(fn) + return sum / this.length + } + + /** 满足条件的元素数量 */ + count(fn: (item: Item) => number): number + { + if (this.length == 0) + return 0 + let c = 0 + for (const item of this) + { + if (fn(item)) + c = c + 1 + } + return c + } + + FindMax(fn: (item: Item) => T): Item + { + return this.reduce((a: Item, b: Item): Item => fn(a) > fn(b) ? a : b) + } +} + +export class ArrayExt +{ + /** 返回满足条件的元素数量 */ + static count(list: Item[], fn: (item: Item) => boolean): number + { + if (list.length == 0) + return 0 + let c = 0 + for (const item of list) + { + if (fn(item)) + c = c + 1 + } + return c + } + + /** 移除 */ + static remove(list: Item[], obj: Item) + { + let index = list.findIndex(t => t == obj) + if (index == -1) + return + list.splice(index, 1) + } + + /** 返回符合条件的第一个元素 */ + static first(list: Item[], fn: (item: Item) => boolean, orderFn1: (item: Item) => number = null, orderFn2: (item: Item) => number = null): Item + { + if (list.length == 0) + return null + if (orderFn1 == null) + { + for (const item of list) + { + if (fn(item)) + return item + } + return null + } + + let minValue1: number + let minValue2: number + let minItem: Item + for (const item of list) + { + if (fn(item) == false) + continue + let v1 = orderFn1(item) + let v2 = orderFn2 != null ? orderFn2(item) : 0 + if (minValue1 == null || v1 < minValue1 || (v1 == minValue1 && v2 < minValue2)) + { + minValue1 = v1 + minValue2 = v2 + minItem = item + } + } + return minItem + } + + /** 返回符合条件的最后一元素 */ + static last(list: Item[], fn: (t: Item) => boolean, orderFn1: (item: Item) => number = null, orderFn2: (item: Item) => number = null): Item + { + if (list.length == 0) + return null + if (orderFn1 == null) + { + for (let i = list.length - 1; i >= 0; i--) + { + if (fn(list[i])) + return list[i] + } + return null + } + + // + let maxValue1: number + let maxValue2: number + let maxItem: Item + for (const item of list) + { + if (fn(item) == false) + continue + let v1 = orderFn1(item) + let v2 = orderFn2 ? orderFn2(item) : 0 + if (maxValue1 == null || v1 > maxValue1 || (v1 == maxValue1 && v2 > maxValue2)) + { + maxValue1 = v1 + maxValue2 = v2 + maxItem = item + } + } + return maxItem + } + + /** 取最大值 */ + static max(list: T1[], fn: (item: T1) => T2, whereF: (item: T1) => boolean = null, defaultV: T2 = null): T2 + { + let maxV: T2 + for (const i of list) + { + if (whereF && whereF(i) == false) + continue + let v = fn(i) + if (maxV == undefined) + { + maxV = fn(i) + } + else + { + if (v > maxV) + { + maxV = v + } + } + } + if (maxV != undefined) + return maxV + return defaultV + } + + /** 最小值 */ + static min(list: Item[], fn: (item: Item) => T, whereF: (item: Item) => boolean = null, defaultV: T = null): T + { + let minV: T + for (const i of list) + { + if (whereF && whereF(i) == false) + continue + let v = fn(i) + if (minV == undefined) + { + minV = v + } + else + { + if (v < minV) + { + minV = v + } + } + } + if (minV != undefined) + return minV + return defaultV + } + + /** 累加 */ + static sum(list: Item[], fn: (item: Item) => number, wn?: (item: Item) => boolean): number + { + let v: number = 0 + for (const t of list) + { + if (wn && wn(t) == false) + continue + v = v + fn(t) + } + return v + } + + /** 平均值 */ + static avg(list: Item[], fn: (item: Item) => number): number + { + if (this.length == 0) + return 0 + let sum = ArrayExt.sum(list, fn) + return sum / this.length + } + + /** 排序 */ + static sortBy(list: Item[], fn: (item: Item) => number, fn2: (item: Item) => number = null) + { + if (fn2 == null) + return list.sort((a: Item, b: Item): number => fn(a) - fn(b)) + else + return list.sort((a: Item, b: Item): number => fn(a) == fn(b) ? (fn2(a) - fn2(b)) : fn(a) - fn(b)) + } + + /** 降序 排序 */ + static sortByDescending(list: Item[], fn: (item: Item) => number) + { + list.sort((a: Item, b: Item): number => fn(b) - fn(a)) + } + + /** 排序成新的数组 */ + static orderBy(list: Item[], fn: (item: Item) => number, fn2: (item: Item) => number = null): Item[] + { + let newList = list.concat([]) + if (fn2 == null) + return newList.sort((a: Item, b: Item): number => fn(a) - fn(b)) + else + return newList.sort((a: Item, b: Item): number => fn(a) == fn(b) ? (fn2(a) - fn2(b)) : fn(a) - fn(b)) + } + + /** 降序成新的数组 */ + static orderByDescending(list: Item[], fn: (item: Item) => number, fn2: (item: Item) => number = null): Item[] + { + let newList = list.concat([]) + if (fn2 == null) + return list.sort((a: Item, b: Item): number => fn(b) - fn(a)) + else + return list.sort((a: Item, b: Item): number => fn(a) == fn(b) ? (fn2(b) - fn2(a)) : fn(b) - fn(a)) + } + + /** 分组 */ + static groupBy(list: Item[], fn: (item: Item) => gT): GroupItem[] + { + let groups = new Array>() + + for (const item of list) + { + let key = fn(item) + let group = groups.find(t => t.key == key) + if (group == null) + { + group = new GroupItem(key) + groups.push(group) + } + group.push(item) + } + return groups + } + + /** + * 选择 + * let newObjectList = ArrayExt.Select(list,t=>({pA:t.name, pB:t.age + "_"+ t.month}) ) ; + */ + static Select(list: Item[], fn: (item: Item) => rT): rT[] + { + let newList = new Array() + for (const t of list) + { + newList.push(fn(t)) + } + return newList + } + + /** 过来,并按顺序排序 */ + static where(list: Item[], whereFn: (item: Item) => boolean, orderfn1: (item: Item) => number = null, orderfn2: (item: Item) => number = null): Item[] + { + let newList = list.filter(whereFn) + if (orderfn1 == null && orderfn2 == null) + return newList + return ArrayExt.sortBy(newList, orderfn1, orderfn2) + } +} + +export class GroupItem +{ + key: gT + get count() { return this.list.length } + list: Item[] + + constructor(k: gT) + { + this.key = k + this.list = [] + } + + push(d: Item) + { + this.list.push(d) + } +} diff --git a/src/modules/cutOrder/KLSCclass.ts b/src/modules/cutOrder/KLSCclass.ts new file mode 100644 index 0000000..2677700 --- /dev/null +++ b/src/modules/cutOrder/KLSCclass.ts @@ -0,0 +1,1523 @@ + + +//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|undefined => + { + 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|undefined, number] => + { + let l_b: YH_bang[] = []; + let cd_l = 0; let cd_r: number = 0; let wzl: number|undefined ; let wzr: number|undefined; + 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|undefined => + { + 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|undefined => + { + 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|undefined => + { + 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|undefined; + 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|undefined; + 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[]; + /**跟别的板关联的ID */ + grid: number; + /**是否为合并的大板 */ + isbig?: boolean; + /**是否被切掉的板 */ + isqg?: boolean; + +} diff --git a/src/processors/cutOrder/CutOrder.ts b/src/processors/cutOrder/CutOrder.ts new file mode 100644 index 0000000..1d7beae --- /dev/null +++ b/src/processors/cutOrder/CutOrder.ts @@ -0,0 +1,124 @@ +import { ProcessorBase, ProcessorContext, CutOrderInput, CutorderOutput, CutorderConfig } from "cut-abstractions"; +import { KLSC, YH_bang } from "../../modules/cutOrder/KLSCclass"; + + + +/** + * 开料顺序 --新算法 + */ +export class CutOrderProc extends ProcessorBase { + get name(): string { + return 'imes-cutOrder'; + } + get version(): string { + return '1.0.0'; + } + exec(context: ProcessorContext): Promise | void { + return new Promise(async (resolve, reject) => { + try { + /** 验证入参 */ + let check = this.checkInput(context?.input) + if (check.isOk == false) { + reject(check.msg) + return + } else { + let bangs: YH_bang[] = [] + let blocks = new Array() + let length = context.input?.blocks.length || 0 + let beginId = 0; + let dt = context.input?.gap || 6; + let k = context.input?.boardWidth || 0; + let g = context.input?.boardHeight || 0; + + for (let i = 0; i < length; i++) { + let block = context.input?.blocks[i]; + let bangid = i + 1; + let x = block?.x; + let y = block?.y; + let pbg = block?.length; + let pbk = block?.width; + blocks[bangid] = block; + + if (x == undefined) { + reject(`block ${block?.id} x is undefined`) + return + } else if (y == undefined) { + reject(`block ${block?.id} y is undefined`) + return + } + else if (pbg == undefined) { + reject(`block ${block?.id} pbg is undefined`) + return + } else if (pbk == undefined) { + reject(`block ${block?.id} pbk is undefined`) + return + } + + bangs.push({ + bangid, + line: 0, + pbg, + pbk, + x, + y, + ishb: false, + hb: [], + isbig: false, + isqg: false, + isgr: false, + gr: [], + grid: -1 + }); + } + let xdsc = new KLSC(bangs, k, g, dt, 0, 0, 1); + let rt = xdsc.SCid; + if (rt.length < length) { + reject('开料顺序算法异常,计算结果与板件数不匹配。') + return + }; + for (let i = 0; i < rt.length; i++) { + let bid = rt[i]; + beginId++; + blocks[bid].cutOrder = beginId; + } + context.output = { + blocks + } + } + resolve() + + } catch (error) { + reject(error); + } + }); + } + + private checkInput(input?: CutOrderInput) { + let info: any = { + isOk: true, + msg: '' + } + if (input == undefined) { + info.isOk = false + info.msg = 'context.input is undefind' + } else if (input.blocks == undefined) { + info.isOk = false + info.msg = 'context.input.blocks is undefind' + } else if (input.gap == undefined) { + info.isOk = false + info.msg = 'context.input.gap is undefind' + } else if (input.boardWidth == undefined) { + info.isOk = false + info.msg = 'context.input.boardWidth is undefind' + } else if (input.boardHeight == undefined) { + info.isOk = false + info.msg = 'context.input.boardHeight is undefind' + } + + + + return info + } + +} + \ No newline at end of file diff --git a/src/processors/cutOrder/cutOrder.test.ts b/src/processors/cutOrder/cutOrder.test.ts new file mode 100644 index 0000000..34a7c48 --- /dev/null +++ b/src/processors/cutOrder/cutOrder.test.ts @@ -0,0 +1,61 @@ +import { test } from 'vitest' +import { CutOrderProc } from './CutOrder'; +import { CutorderConfig, CutOrderInput, CutorderInputBlock } from 'cut-abstractions'; + +test('cutOrderTest', async () => { + + let cutOrderProc = new CutOrderProc() + let params: CutorderConfig = new CutorderConfig() + + let blocks: CutorderInputBlock[] = [ + { + id: 25030882560, + length: 598, + width: 398, + x: 3.005, + y: 4, + }, + { + id: 25030882561, + length: 598, + width: 398, + x: 3.005, + y: 610, + }, + { + id: 25030882562, + length: 598, + width: 398, + x: 3.005, + y: 1216, + }, + { + id: 25030882563, + length: 598, + width: 398, + x: 3.005, + y: 1821.005, + }, + { + id: 25030882564, + length: 598, + width: 398, + x: 407.015, + y: 3.005, + }, + ] + + let input: CutOrderInput = { + boardWidth: 1220, + boardHeight: 2440, + gap: 6, + blocks + } + const context = { + input, + params + } + await cutOrderProc.exec(context) + // 将在context的output中显示结果 + console.log(context); +}) \ No newline at end of file diff --git a/src/processors/cutPoint/CutPoint.ts b/src/processors/cutPoint/CutPoint.ts new file mode 100644 index 0000000..53785b2 --- /dev/null +++ b/src/processors/cutPoint/CutPoint.ts @@ -0,0 +1,428 @@ +import { ArrayExt } from "@libs/modules/cutOrder/ArrayExt"; +import { ConfigBase, CutorderoutputBlock, ProcessorBase, ProcessorContext } from "cut-abstractions"; + + + +/** + * 下刀点 + */ +export class CutPointProc extends ProcessorBase { + get name(): string { + return 'imes-cutPoint'; + } + get version(): string { + return '1.0.0'; + } + /** 刀路间距 */ + private gap = 7 + /** 走刀100内 不能算靠板 */ + private cutedSpace = 100 + /** 垂直线, x ,y1,y2 */ + private lines_V: type_lines_V[] = [] + /** 水平线 x1,x2, y */ + private lines_H: type_lines_H[] = [] + exec(context: ProcessorContext): Promise | void { + return new Promise(async (resolve, reject) => { + try { + this.gap = context.input?.gap || 7 + this.lines_H = []; //开料水平线 + this.lines_V = []; //开料垂直线 + if (Array.isArray(context.input?.boardPointInfo?.pts) && context.input?.boardPointInfo?.pts?.length > 0) { + for (let i = 0; i < context.input.boardPointInfo?.pts.length; i++) { + let j = i + 1; + if (j == context.input.boardPointInfo?.pts.length) j = 0; + this.pushLine(context.input.boardPointInfo.pts[i], context.input.boardPointInfo.pts[j]); + } + } else { + if (context.input?.boardWidth && context.input?.boardHeight) { + let p0 = { x: 0, y: 0 }; + let p1 = { x: context.input.boardWidth, y: 0 }; + let p2 = { x: context.input.boardWidth, y: context.input.boardHeight }; + let p3 = { x: 0, y: context.input.boardHeight }; + this.pushLine(p0, p1); + this.pushLine(p1, p2); + this.pushLine(p2, p3); + this.pushLine(p3, p0); + } else { + reject('imes-cutPoint error:input.boardWidth or input.boardHeight is undefined') + } + } + + let blocks = context.input?.blocks?.sort((a, b) => a.cutOrder - b.cutOrder) || [] + + if (blocks.length == 0) { + reject('imes-cutPoint error:input.blocks no data!') + } + for (let b of blocks) { + this.findCutPoint(b); + } + + resolve() + } catch (error) { + reject(error); + } + }); + } + /** 计算下刀点 */ + private findCutPoint(block: CutPointInputBlock) { + let list = block.blockPoints.pts + //计算没边的靠板情况,并自动生成 铣板走线 数据 + let borders_cuting = []; + for (let i = 0; i < list.length; i++) { + let rt = this.getUnCutedLength(block, list, i); + + borders_cuting.push([i, rt[0], rt[1]]); + + } + } + + /**获取未切边长度 */ + private getUnCutedLength(block: CutPointInputBlock, curs: IPoint[], i: number): [number, number] { + + let cur = curs[i]; + let next = i + 1 + if (next == curs.length - 1) { + next = 0 + } + let curNext = curs[next] + + let p1 = { x: block.x + cur.x, y: block.y + cur.y }; + let p2 = { x: block.x + curNext.x, y: block.y + curNext.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.x, 0) || this.qual(cur.y, block.length)); + if (isborder == false) { + isborder = isCZ && (this.qual(cur.x, 0) || this.qual(cur.x, block.width)); + } + + if (isborder == false) { + for (let j = 0; j < curs.length; j++) { + if (i == j) continue; + let other = curs[j]; + let k = j + 1 + if (k == curs.length - 1) { + k = 0 + } + let otherNext = curs[k] + if (isSP && this.qual(other.y, otherNext.y)) //水平,line 在板内 + { + if (this.qual(other.y, 0)) continue; //边缘线,不计算 + if (this.qual(other.y, block.length)) continue; + + if (this.qual(cur.y, other.y, 100)) { + unCutedLength = 0; + break; + } + } + else { + if (isCZ && this.qual(other.x, otherNext.x)) { + if (this.qual(other.x, 0)) continue; + if (this.qual(other.x, block.width)) continue; + + if (this.qual(cur.x, other.x, 100)) { + unCutedLength = 0; + break; + } + } + } + } + + } + + + } + return [unCutedLength, cutedSize]; + } + + /**获取水平开料边长度 */ + private getcutedLength_h(p1: IPoint, p2: IPoint): [number, number, number, number, number] //cutedLength,x1,x2,y + { + let x1: number; + let x2: number; + + 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 getcutedLength_v(p1: IPoint, p2: IPoint): [number, number, number, number, number] //cutedLength,x,y1,y2 + { + let x = p1.x; + + let y1: number; + let y2: number; + 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]; + + + } + + /**保存刀路 */ + private pushLine(p1: IPoint, p2: IPoint) { + 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 pushline_H(x1: number, x2: number, y: number) { + this.lines_H.push({ x1: Math.min(x1, x2), x2: Math.max(x1, x2), y: y }); + } + + /**保存竖直刀路 */ + private pushline_V(x: number, y1: number, y2: number) { + this.lines_V.push({ x: x, y1: Math.min(y1, y2), y2: Math.max(y1, y2) }); + } + /**判断是否相等 */ + private qual(x: number, y: number, off = 0.005): boolean { + return Math.abs(x - y) < off; + } +} + +type type_lines_V = { + x: number, + y1: number, + y2: number +} + +type type_lines_H = { + x1: number, + x2: number, + y: number +} + + + +/** + * 下刀点 入参 + */ +export type CutPointInput = { + /** 刀路间距 */ + gap: number, + /** (余料板异形点) 开料大板的开料轮廓数据 若没有则需要传 开料大板宽、高*/ + boardPointInfo?: IProcessingItem, + /** 开料大板宽 若有 boardPointInfo 则不需要传 */ + boardWidth?: number, + /** 开料大板高 若有 boardPointInfo 则不需要传 */ + boardHeight?: number + /** 小板数据集 */ + blocks?: CutPointInputBlock[] +} +/** 处理器输出---下刀点 */ +export type CutPointOutput = { + blocks: CutPointOutputBlock[] +} + +/** + * 小板类型 输入 + */ +export type CutPointInputBlock = { + /** 小板唯一标识 */ + id: string | number; + /** 排版长 */ + length: number; + /** 排版宽 */ + width: number; + /** 板件坐标X */ + x: number; + /** 板件坐标y */ + y: number; + /** 开料顺序 */ + cutOrder: number; + /** + * 板件轮廓 + * 用以分析下刀点的板件轮廓 + * */ + blockPoints: IProcessingItem + /** 是否异形 true 是异形 false 矩形 */ + isUnRegular: boolean +}; + +/** 小板类型 输出 */ +export type CutPointOutputBlock = CutPointInputBlock & { + /** 下刀点 板件轮廓的下标 */ + cutPointId: number, +} + +/** 下刀点配置 + * + * 注:暂时没有配置项 + */ +export declare class CutPointConfig extends ConfigBase { +} + + +export interface IPoint { x: number, y: number; } +/** + * 加工数据 + */ +export interface IProcessingItem { + /** + * 加工点数组 + */ + pts: IPoint[]; + /** + * 凸度数组 + */ + buls: number[]; + +} + diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..ae94125 --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,39 @@ +{ + // TODO: Warn: 在进行TS类型检查的时候会检查到workflow工作区中的文件,原因未知 + "compilerOptions": { + "lib": [ + "ES2020", + "ES2021", + "ESNext", + "DOM", + "DOM.Iterable" + ], + "noEmit": true, + "target": "esnext", + "module": "ESNext", + "moduleResolution": "Bundler", + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "baseUrl": ".", + "paths": { + // 为了保证导入不与被引入项目冲突,不应该配置'@/*'别名 + "@libs/*": [ + "./src/*" + ] + }, + /* Linting */ + "strict": true, + "erasableSyntaxOnly": false, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true, + "composite": true + }, + "include": [ + "src/**/*.ts", + "src/**/*.tsx", + ], + "exclude": [ + "src/**/__tests__/*", + "dist", + "node_modules/**" + ] +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..1ffef60 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..dcf15c3 --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "target": "ES2023", + "lib": ["ES2023"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true, + }, + "include": ["vite.config.ts"] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..a488e90 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,34 @@ +/// +import { defineConfig } from 'vite' +import { nodePolyfills } from 'vite-plugin-node-polyfills'; +import { resolve } from 'node:path'; +import dts from 'vite-plugin-dts'; + +let basePath = process.env.basePath ?? ''; + +// https://vite.dev/config/ +export default defineConfig({ + base: basePath, + plugins: [ + nodePolyfills(), + dts({rollupTypes: true, tsconfigPath: './tsconfig.app.json',insertTypesEntry: true}), + ], + build: { + modulePreload: { + resolveDependencies() { + return []; + } + }, + lib: { + entry: resolve(__dirname, 'src/index.ts'), + name: 'MesCutorder', + fileName(format) { + return `mes-cutorder.${format}.js` + }, + formats: ['es', 'umd', 'iife'] + } + }, + esbuild: { + drop: process.env.NODE_ENV === 'production' ? ['console', 'debugger'] : [], + }, +}) \ No newline at end of file