feat:提交
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
*.tgz
|
||||||
|
node_modules/*
|
||||||
|
*.yaml
|
||||||
|
dist/*
|
111
README.md
Normal file
111
README.md
Normal file
@@ -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中进行登录,并确保你有该仓库的访问权限。
|
||||||
|
> - 库的版本需要手动进行控制,注意上述链接中的版本信息,在安装前需要主动修改版本号,请前往<http://gitea.cf/MES-FE/mes-packages/releases>来确认最新版本。
|
||||||
|
|
||||||
|
## 使用
|
||||||
|
|
||||||
|
该库提供了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<typeo
|
||||||
|
await proc.exec(ctx);
|
||||||
|
|
||||||
|
// 从上下文对象中获取输出内容
|
||||||
|
console.log("RESULT: ", ctx.output);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Q&A
|
||||||
|
|
||||||
|
### 运行某些处理器时出现404(Not Found)错误
|
||||||
|
|
||||||
|
**错误描述**
|
||||||
|
当执行处理器时,出现类似下面的错误:
|
||||||
|
|
||||||
|
```log
|
||||||
|
GET http://localhost:5173/node_modules/.vite/deps/assets/RectOptimizeMachine.worker-BO2fmpVH.js 404 (Not Found)
|
||||||
|
```
|
||||||
|
|
||||||
|
**根本原因**
|
||||||
|
该库中某些处理器使用了Web Worker来实现多线程异步处理(例如矩形优化处理器)。
|
||||||
|
|
||||||
|
Web Worker为单独打包的资产文件,但某些打包工具可能会对`node_modules`中的依赖进行预构建来提高性能,如果Worker文件被视为了预构建的一部分,就可能导致处理器无法正确地处理Worker文件的相对引用路径,导致在运行时尝试从`node_modules/.vite/deps/assets/`这样的内部路径加载,而这个路径在实际部署或服务时是不存在的。
|
||||||
|
|
||||||
|
**解决方法**
|
||||||
|
在打包工具中对该库进行配置,禁用对该库的优化和预构建,以`vite`为例:
|
||||||
|
```ts
|
||||||
|
// vite.config.ts
|
||||||
|
...
|
||||||
|
optimizeDeps: {
|
||||||
|
exclude: ["@mes-processors/libs"] // 从optimizeDeps中排除该库
|
||||||
|
}
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
## 开发
|
||||||
|
|
||||||
|
### 发布并打包项目
|
||||||
|
|
||||||
|
```sh
|
||||||
|
pnpm build
|
||||||
|
pnpm pack
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!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
|
||||||
|
```
|
38
package.json
Normal file
38
package.json
Normal file
@@ -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"
|
||||||
|
}
|
8
src/index.ts
Normal file
8
src/index.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @package @mes-processors/libs
|
||||||
|
* @author LX
|
||||||
|
* @description 工作流处理器类库,在这个文件中使用导出时,不要在路径中使用'@',否则模块无法加载
|
||||||
|
*/
|
||||||
|
|
||||||
|
// CutOrder
|
||||||
|
export * from "./processors/cutOrder/CutOrder";
|
2
src/modules/README.md
Normal file
2
src/modules/README.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
### react-layout
|
||||||
|
矩形优化算法(陈总新优化)
|
375
src/modules/cutOrder/ArrayExt.ts
Normal file
375
src/modules/cutOrder/ArrayExt.ts
Normal file
@@ -0,0 +1,375 @@
|
|||||||
|
export class List<Item> extends Array<Item>
|
||||||
|
{
|
||||||
|
/** 返回符合条件的第一个元素 */
|
||||||
|
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<T>(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<T>(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<T>(fn: (item: Item) => T): Item
|
||||||
|
{
|
||||||
|
return this.reduce((a: Item, b: Item): Item => fn(a) > fn(b) ? a : b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ArrayExt
|
||||||
|
{
|
||||||
|
/** 返回满足条件的元素数量 */
|
||||||
|
static count<Item>(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<Item>(list: Item[], obj: Item)
|
||||||
|
{
|
||||||
|
let index = list.findIndex(t => t == obj)
|
||||||
|
if (index == -1)
|
||||||
|
return
|
||||||
|
list.splice(index, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 返回符合条件的第一个元素 */
|
||||||
|
static first<Item>(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<Item>(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<T1, T2>(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<Item, T>(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<Item>(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<Item>(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<Item>(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<Item>(list: Item[], fn: (item: Item) => number)
|
||||||
|
{
|
||||||
|
list.sort((a: Item, b: Item): number => fn(b) - fn(a))
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 排序成新的数组 */
|
||||||
|
static orderBy<Item>(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<Item>(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<Item, gT>(list: Item[], fn: (item: Item) => gT): GroupItem<gT, Item>[]
|
||||||
|
{
|
||||||
|
let groups = new Array<GroupItem<gT, Item>>()
|
||||||
|
|
||||||
|
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<Item, rT>(list: Item[], fn: (item: Item) => rT): rT[]
|
||||||
|
{
|
||||||
|
let newList = new Array<rT>()
|
||||||
|
for (const t of list)
|
||||||
|
{
|
||||||
|
newList.push(fn(t))
|
||||||
|
}
|
||||||
|
return newList
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 过来,并按顺序排序 */
|
||||||
|
static where<Item>(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<gT, Item>
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
1523
src/modules/cutOrder/KLSCclass.ts
Normal file
1523
src/modules/cutOrder/KLSCclass.ts
Normal file
File diff suppressed because it is too large
Load Diff
124
src/processors/cutOrder/CutOrder.ts
Normal file
124
src/processors/cutOrder/CutOrder.ts
Normal file
@@ -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<CutOrderInput, CutorderOutput, CutorderConfig> {
|
||||||
|
get name(): string {
|
||||||
|
return 'imes-cutOrder';
|
||||||
|
}
|
||||||
|
get version(): string {
|
||||||
|
return '1.0.0';
|
||||||
|
}
|
||||||
|
exec(context: ProcessorContext<CutOrderInput, CutorderOutput, CutorderConfig>): Promise<void> | 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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
61
src/processors/cutOrder/cutOrder.test.ts
Normal file
61
src/processors/cutOrder/cutOrder.test.ts
Normal file
@@ -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);
|
||||||
|
})
|
428
src/processors/cutPoint/CutPoint.ts
Normal file
428
src/processors/cutPoint/CutPoint.ts
Normal file
@@ -0,0 +1,428 @@
|
|||||||
|
import { ArrayExt } from "@libs/modules/cutOrder/ArrayExt";
|
||||||
|
import { ConfigBase, CutorderoutputBlock, ProcessorBase, ProcessorContext } from "cut-abstractions";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下刀点
|
||||||
|
*/
|
||||||
|
export class CutPointProc extends ProcessorBase<CutPointInput, CutPointOutput, CutPointConfig> {
|
||||||
|
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<CutPointInput, CutPointOutput, CutPointConfig>): Promise<void> | 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[];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
1
src/vite-env.d.ts
vendored
Normal file
1
src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/// <reference types="vite/client" />
|
39
tsconfig.app.json
Normal file
39
tsconfig.app.json
Normal file
@@ -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/**"
|
||||||
|
]
|
||||||
|
}
|
7
tsconfig.json
Normal file
7
tsconfig.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"files": [],
|
||||||
|
"references": [
|
||||||
|
{ "path": "./tsconfig.app.json" },
|
||||||
|
{ "path": "./tsconfig.node.json" }
|
||||||
|
]
|
||||||
|
}
|
25
tsconfig.node.json
Normal file
25
tsconfig.node.json
Normal file
@@ -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"]
|
||||||
|
}
|
34
vite.config.ts
Normal file
34
vite.config.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
/// <reference types="vitest/config" />
|
||||||
|
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'] : [],
|
||||||
|
},
|
||||||
|
})
|
Reference in New Issue
Block a user