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