wall-window-matcher 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,176 @@
1
+ # wall-window-matcher
2
+
3
+ > 建筑点云数据 —— 墙线段合并 + 窗户匹配 + drawWindow 属性注入工具
4
+
5
+ **纯算法、无 Node 文件系统依赖,可在浏览器 / Vite / Node 中直接使用。**
6
+
7
+ ## 功能
8
+
9
+ 1. **墙线段共线合并**:将方向相近、距离很近的多条墙段合并成一条更长的线段
10
+ 2. **窗户-墙体匹配**:基于坐标投影与距离判定,将 `category === 'window'` 的物体匹配到最近的墙上
11
+ 3. **drawWindow 属性注入**:在匹配成功的墙线段上新增 `drawWindow[]` 数组,记录窗户信息(位置、宽高、离地高度)
12
+ 4. **保留原始字段**:合并时保留原始线段的 `points`、`boxData`、`doorAndBeamData` 等所有字段
13
+
14
+ ## 安装
15
+
16
+ ```bash
17
+ npm install wall-window-matcher
18
+ ```
19
+
20
+ 或者直接从本地包引入(通过 vite alias 指向 `packages/wall-window-matcher/src/index.ts`)。
21
+
22
+ ## 快速开始
23
+
24
+ ```ts
25
+ import { processData, findWindowWalls, mergeCollinearSegments } from 'wall-window-matcher'
26
+
27
+ // 墙线段数组(从点云分割/墙体检测工具导出)
28
+ const wallSegments = [
29
+ { start: { x: 0, y: 0, z: -1.3 }, end: { x: 5, y: 0, z: -1.3 }, length: 5, rooftopPz: 1.2, ... },
30
+ // ...
31
+ ]
32
+
33
+ // 物体数组(其中 category === 'window' 的会被处理)
34
+ const objects = [
35
+ { category: 'window', center: { x: 2.5, y: 0.1, z: 0.2 }, width: 1.5, height: 1.2, ... },
36
+ // ...
37
+ ]
38
+
39
+ // 主入口:合并线段 + 匹配窗户 + 注入 drawWindow
40
+ const result = processData(wallSegments, objects)
41
+ console.log('合并后墙线段数:', result.segments.length)
42
+ console.log('匹配成功数:', result.matches.length)
43
+ console.log('sourceMap 对应关系:', result.sourceMap)
44
+
45
+ // segments 中的每条线段如果有匹配,会包含 drawWindow 数组
46
+ for (const seg of result.segments) {
47
+ if (seg.drawWindow && seg.drawWindow.length > 0) {
48
+ console.log('该墙有', seg.drawWindow.length, '个窗户')
49
+ }
50
+ }
51
+ ```
52
+
53
+ ## API
54
+
55
+ ### `processData(wallSegments, windowObjects, options?)`
56
+
57
+ 主函数,一次性完成合并 + 匹配 + 属性注入。
58
+
59
+ ```ts
60
+ function processData(
61
+ wallSegments: WallSegment[],
62
+ windowObjects: WindowObject[],
63
+ options?: FindWallOptions & { printOnly?: boolean },
64
+ ): {
65
+ segments: WallSegment[]; // 合并后的墙线段(含 drawWindow 注入)
66
+ matches: WallWindowMatch[]; // 匹配详情列表
67
+ sourceMap: number[][]; // 每条输出线段对应的原始线段索引
68
+ }
69
+ ```
70
+
71
+ ### `findWindowWalls(windowObjects, wallSegments, options?)`
72
+
73
+ 只做窗户-墙体匹配,不合并。
74
+
75
+ ### `mergeCollinearSegments(segments)`
76
+
77
+ 只做墙线段共线合并,返回 `{ segments, sourceMap, debugRPZGroups }`。
78
+
79
+ ### `computeLocalFloorZ(points)`
80
+
81
+ 从一组点云计算局部地板 Z 值,用于判断窗户离地高度。
82
+
83
+ ## 类型定义
84
+
85
+ ```ts
86
+ interface WallSegment {
87
+ start: Point3D; // { x, y, z }
88
+ end: Point3D; // { x, y, z }
89
+ length: number;
90
+ direction: { x: number; y: number; z: number };
91
+ rooftopPz?: number; // 屋顶 Z
92
+ buildRosource?: string; // 来源标识
93
+ isRebuild?: boolean;
94
+ points?: Point3D[]; // 原始点云(可能非常大)
95
+ boxData?: any;
96
+ doorAndBeamData?: any[];
97
+ insetionArr?: any[];
98
+ drawWindow?: DrawWindow[]; // 新增字段:匹配到的窗户
99
+ [key: string]: any;
100
+ }
101
+
102
+ interface WindowObject {
103
+ category: string; // 'window'
104
+ center?: Point3D;
105
+ width?: number;
106
+ height?: number;
107
+ [key: string]: any;
108
+ }
109
+
110
+ interface DrawWindow {
111
+ p: Point3D;
112
+ width: number;
113
+ height: number;
114
+ groundClearance: number;
115
+ full: boolean;
116
+ }
117
+ ```
118
+
119
+ ## Node 服务调用示例
120
+
121
+ 在 Node 服务中读取本地 JSON,调用 npm 包处理后直接返回大 JSON 响应:
122
+
123
+ ```ts
124
+ import { processData } from 'wall-window-matcher'
125
+ import { readFileSync } from 'fs'
126
+
127
+ const walls = JSON.parse(readFileSync('PJ1781665824Wxs___finalLines.json', 'utf-8'))
128
+ const objects = JSON.parse(readFileSync('PJ1781665824Wxs_pcdPointsArr.json', 'utf-8'))
129
+ const windowObjects = objects.filter((o: any) => o.category === 'window')
130
+
131
+ const result = processData(walls, windowObjects)
132
+ console.log('合并后:', result.segments.length, '条')
133
+ ```
134
+
135
+ 或者通过 HTTP 接口:
136
+
137
+ ```bash
138
+ # 默认返回完整处理后的大 JSON(59 条线段,含 points 等原始字段)
139
+ curl -X POST http://localhost:3030/api/pcs/process \
140
+ -H "Content-Type: application/json" \
141
+ -d '{"pjName":"PJ1781665824Wxs"}'
142
+
143
+ # 只返回被修改过的线段(合并过的 / 新增了 drawWindow 的)
144
+ curl -X POST http://localhost:3030/api/pcs/process \
145
+ -H "Content-Type: application/json" \
146
+ -d '{"pjName":"PJ1781665824Wxs","outputChanged":true}'
147
+ ```
148
+
149
+ ## CLI(仅 Node 环境)
150
+
151
+ ```bash
152
+ # 直接运行(需要 tsx)
153
+ npx tsx packages/wall-window-matcher/src/cli.ts \
154
+ path/to/walls.json path/to/objects.json
155
+
156
+ # 或在 npm pack 后的 dist 中
157
+ npm run build # 编译 TS → dist/
158
+ node dist/cli.js walls.json objects.json
159
+ ```
160
+
161
+ ## 项目结构
162
+
163
+ ```
164
+ packages/wall-window-matcher/
165
+ ├── src/
166
+ │ ├── index.ts # 主入口(浏览器 / Node 通用,无 fs 依赖)
167
+ │ ├── findWindowWall.ts # 核心算法:合并 + 匹配 + 类型定义
168
+ │ └── cli.ts # Node CLI 工具(含 fs 依赖)
169
+ ├── package.json
170
+ ├── tsconfig.json
171
+ └── README.md
172
+ ```
173
+
174
+ ## License
175
+
176
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ import { WallSegment, FindWallOptions } from './index';
3
+ export declare function processFiles(segmentsPath: string, objectsPath: string, outputPath?: string, options?: FindWallOptions & {
4
+ printOnly?: boolean;
5
+ }): WallSegment[];
6
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAMA,OAAO,EAAe,WAAW,EAAgB,eAAe,EAAE,MAAM,SAAS,CAAA;AAOjF,wBAAgB,YAAY,CAC1B,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,EACnB,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,eAAe,GAAG;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAClD,WAAW,EAAE,CAgBf"}
package/dist/cli.js ADDED
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ // wall-window-matcher CLI —— 仅用于 Node 环境
4
+ // 用法:npx tsx src/cli.ts <walls.json> <objects.json> [output.json] [--print-only]
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.processFiles = processFiles;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const index_1 = require("./index");
43
+ function readJSON(filePath) {
44
+ const raw = fs.readFileSync(filePath, 'utf-8');
45
+ return JSON.parse(raw);
46
+ }
47
+ function processFiles(segmentsPath, objectsPath, outputPath, options) {
48
+ console.log(`[wall-window-matcher] 读取墙线段: ${segmentsPath}`);
49
+ const wallSegments = readJSON(segmentsPath);
50
+ console.log(`[wall-window-matcher] 读取物体数据: ${objectsPath}`);
51
+ const objects = readJSON(objectsPath);
52
+ const windowObjects = objects.filter((o) => o.category === 'window');
53
+ console.log(`[wall-window-matcher] 墙线段: ${wallSegments.length} 条,窗户: ${windowObjects.length} 个`);
54
+ const { segments } = (0, index_1.processData)(wallSegments, windowObjects, options);
55
+ const outPath = outputPath || segmentsPath.replace(/\.json$/, '_enhanced.json');
56
+ fs.writeFileSync(outPath, JSON.stringify(segments, null, 2), 'utf-8');
57
+ console.log(`[wall-window-matcher] 输出: ${outPath}`);
58
+ return segments;
59
+ }
60
+ // ---- CLI 入口 ----
61
+ const args = process.argv.slice(2);
62
+ if (args.length >= 2) {
63
+ const segmentsFile = path.resolve(args[0]);
64
+ const objectsFile = path.resolve(args[1]);
65
+ const outputFile = args[2] && !args[2].startsWith('--') ? path.resolve(args[2]) : undefined;
66
+ const printOnly = args.includes('--print-only');
67
+ console.log('=== wall-window-matcher CLI ===');
68
+ processFiles(segmentsFile, objectsFile, outputFile, { printOnly });
69
+ }
70
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;AACA,yCAAyC;AACzC,iFAAiF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWjF,oCAqBC;AA9BD,uCAAwB;AACxB,2CAA4B;AAC5B,mCAAiF;AAEjF,SAAS,QAAQ,CAAI,QAAgB;IACnC,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAM,CAAA;AAC7B,CAAC;AAED,SAAgB,YAAY,CAC1B,YAAoB,EACpB,WAAmB,EACnB,UAAmB,EACnB,OAAmD;IAEnD,OAAO,CAAC,GAAG,CAAC,gCAAgC,YAAY,EAAE,CAAC,CAAA;IAC3D,MAAM,YAAY,GAAG,QAAQ,CAAgB,YAAY,CAAC,CAAA;IAC1D,OAAO,CAAC,GAAG,CAAC,iCAAiC,WAAW,EAAE,CAAC,CAAA;IAC3D,MAAM,OAAO,GAAG,QAAQ,CAAiB,WAAW,CAAC,CAAA;IAErD,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAA;IACzE,OAAO,CAAC,GAAG,CAAC,8BAA8B,YAAY,CAAC,MAAM,UAAU,aAAa,CAAC,MAAM,IAAI,CAAC,CAAA;IAEhG,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAA,mBAAW,EAAC,YAAY,EAAE,aAAa,EAAE,OAAO,CAAC,CAAA;IAEtE,MAAM,OAAO,GAAG,UAAU,IAAI,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAA;IAC/E,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAA;IACrE,OAAO,CAAC,GAAG,CAAC,6BAA6B,OAAO,EAAE,CAAC,CAAA;IAEnD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,mBAAmB;AACnB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;AAClC,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;IACrB,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;IAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;IACzC,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAC3F,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAA;IAE/C,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAA;IAC9C,YAAY,CAAC,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,CAAC,CAAA;AACpE,CAAC"}
@@ -0,0 +1,154 @@
1
+ /**
2
+ * 找到每个窗户物体所对应的墙体线段
3
+ *
4
+ * 核心思路:
5
+ * 1. 解析窗户四边形的4个角点,计算窗户中心、长边长度、长边方向
6
+ * 2. 对每条墙线段做粗筛(长度 >= 窗户长边 × 1.0,即墙至少与窗等长)
7
+ * 3. 精筛:计算窗户中心到墙线的垂直距离,垂足必须在线段范围内
8
+ * 4. 方向约束:墙线方向应与窗户长边方向平行(夹角 < 45°)
9
+ * 5. 按距离升序取最优匹配
10
+ */
11
+ export interface Point3D {
12
+ x: number;
13
+ y: number;
14
+ z: number;
15
+ }
16
+ /** 窗户在线段上的标记(用于 drawWindow 新字段)*/
17
+ export interface DrawWindow {
18
+ p: Point3D;
19
+ width: number;
20
+ full: boolean;
21
+ height: number;
22
+ groundClearance: number;
23
+ }
24
+ /** 某个不一致 rooftopPz 组中的单条线段调试信息 */
25
+ export interface RPZDebugSegment {
26
+ idx: number;
27
+ start: Point3D;
28
+ end: Point3D;
29
+ length: number;
30
+ rooftopPz: number;
31
+ }
32
+ /** 共线但 rooftopPz 不一致的线段组 */
33
+ export interface RPZDebugGroup {
34
+ values: string[];
35
+ segments: RPZDebugSegment[];
36
+ }
37
+ export interface WallSegment {
38
+ start: Point3D;
39
+ end: Point3D;
40
+ length: number;
41
+ direction: Point3D;
42
+ points: Point3D[];
43
+ originalPoints?: Point3D[];
44
+ isRebuild?: boolean;
45
+ rooftopPz?: number;
46
+ buildRosource?: string;
47
+ doorAndBeamData?: unknown[];
48
+ insetionArr?: unknown[];
49
+ boxData?: {
50
+ isBox3: boolean;
51
+ min: Point3D;
52
+ max: Point3D;
53
+ };
54
+ drawWindow?: DrawWindow[];
55
+ }
56
+ export interface WindowObject {
57
+ name: string;
58
+ category: string;
59
+ center: Point3D;
60
+ box: {
61
+ min: Point3D;
62
+ max: Point3D;
63
+ };
64
+ coordinatesByArea: {
65
+ coordinates: Point3D[];
66
+ heightData?: {
67
+ minZ: number;
68
+ maxZ: number;
69
+ };
70
+ };
71
+ [key: string]: unknown;
72
+ }
73
+ export interface WindowWallMatch {
74
+ /** 窗户名称 */
75
+ windowName: string;
76
+ /** 窗户分类 */
77
+ windowCategory: string;
78
+ /** 窗户中心 (世界坐标) */
79
+ windowCenter: Point3D;
80
+ /** 匹配到的墙线段 */
81
+ wallSegment: WallSegment;
82
+ /** 窗户中心到墙线的垂直距离 (m) */
83
+ distance: number;
84
+ /** 墙线长度 / 窗户长边 */
85
+ wallLengthRatio: number;
86
+ /** drawWindow 数据(窗户在墙上的位置/尺寸)*/
87
+ drawWindow?: DrawWindow;
88
+ }
89
+ export interface FindWallOptions {
90
+ /**
91
+ * 墙线长度至少为窗户长边的倍数,默认 1.0
92
+ * 用于排除过短的杂线,设为 1.0 表示墙至少与窗等长
93
+ */
94
+ minLengthRatio?: number;
95
+ /**
96
+ * 窗户中心到墙线的最大垂直距离 (m),默认 0.5
97
+ * 超出此距离认为不在此墙上
98
+ */
99
+ maxDistance?: number;
100
+ /**
101
+ * 墙线与窗户长边方向的最大夹角 (°),默认 45
102
+ * 墙应大致平行于窗户的水平方向
103
+ */
104
+ angleThreshold?: number;
105
+ /**
106
+ * 垂足在线段上的容许范围,默认 [-0.1, 1.1]
107
+ * 略放宽边界以包容线段提取误差
108
+ */
109
+ projectionMargin?: number;
110
+ /**
111
+ * 是否仅打印核对信息而不写入 drawWindow 字段,默认 true(仅打印)。
112
+ * 核对无误后设为 false,会将 drawWindow 写入墙线段对象。
113
+ */
114
+ printOnly?: boolean;
115
+ }
116
+ /** 两点在 XY 平面上的距离 */
117
+ export declare function dist2D(a: Point3D, b: Point3D): number;
118
+ /** 计算四边形最长边及其方向 (XY 平面) */
119
+ export declare function analyzeQuad(corners: Point3D[]): {
120
+ longSide: number;
121
+ dirX: number;
122
+ dirY: number;
123
+ };
124
+ /** 从墙线段集合中估算地面高度 (Z 轴中位数) */
125
+ /** 基于窗户附近墙线段计算局部地面 Z(半径 3m) */
126
+ export declare function computeLocalFloorZ(walls: WallSegment[], cx: number, cy: number): number;
127
+ /**
128
+ * 计算点 C 到线段 AB 的垂直距离与投影参数 t
129
+ * 返回 { dist, t },t ∈ [0,1] 表示垂足在线段上
130
+ */
131
+ export declare function pointToSegmentDist(cx: number, cy: number, ax: number, ay: number, bx: number, by: number): {
132
+ dist: number;
133
+ t: number;
134
+ };
135
+ /**
136
+ * 合并共线且相邻的墙线段
137
+ *
138
+ * 思路:
139
+ * 1. 将每条线段的方向无向化到 [0°, 180°),按角度分桶(±5° 容差)
140
+ * 2. 每个桶内计算线段到参考线的垂直距离,进一步按共线关系分组
141
+ * 3. 每组内投影到方向轴上,合并重叠/相邻的区间
142
+ *
143
+ * @param segments 原始墙线段列表
144
+ * @param angleTol 角度容差 (°),默认 5
145
+ * @param gapTol 间隙容差 (m),默认 0.05,小于此值的间隙视为相连
146
+ * @returns 合并后的墙线段列表
147
+ */
148
+ export declare function mergeCollinearSegments(segments: WallSegment[], angleTol?: number, gapTol?: number): {
149
+ segments: WallSegment[];
150
+ sourceMap: number[][];
151
+ debugRPZGroups?: RPZDebugGroup[];
152
+ };
153
+ export declare function findWindowWalls(windowObjs: WindowObject[], wallSegments: WallSegment[], options?: FindWallOptions): WindowWallMatch[];
154
+ //# sourceMappingURL=findWindowWall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findWindowWall.d.ts","sourceRoot":"","sources":["../src/findWindowWall.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,693 @@
1
+ "use strict";
2
+ /**
3
+ * 找到每个窗户物体所对应的墙体线段
4
+ *
5
+ * 核心思路:
6
+ * 1. 解析窗户四边形的4个角点,计算窗户中心、长边长度、长边方向
7
+ * 2. 对每条墙线段做粗筛(长度 >= 窗户长边 × 1.0,即墙至少与窗等长)
8
+ * 3. 精筛:计算窗户中心到墙线的垂直距离,垂足必须在线段范围内
9
+ * 4. 方向约束:墙线方向应与窗户长边方向平行(夹角 < 45°)
10
+ * 5. 按距离升序取最优匹配
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.dist2D = dist2D;
14
+ exports.analyzeQuad = analyzeQuad;
15
+ exports.computeLocalFloorZ = computeLocalFloorZ;
16
+ exports.pointToSegmentDist = pointToSegmentDist;
17
+ exports.mergeCollinearSegments = mergeCollinearSegments;
18
+ exports.findWindowWalls = findWindowWalls;
19
+ // ---- 工具函数 ----
20
+ /** 两点在 XY 平面上的距离 */
21
+ function dist2D(a, b) {
22
+ const dx = a.x - b.x;
23
+ const dy = a.y - b.y;
24
+ return Math.sqrt(dx * dx + dy * dy);
25
+ }
26
+ /** 计算四边形最长边及其方向 (XY 平面) */
27
+ function analyzeQuad(corners) {
28
+ let maxLen = 0;
29
+ let dirX = 0;
30
+ let dirY = 0;
31
+ for (let i = 0; i < 4; i++) {
32
+ const a = corners[i];
33
+ const b = corners[(i + 1) % 4];
34
+ const dx = b.x - a.x;
35
+ const dy = b.y - a.y;
36
+ const len = Math.sqrt(dx * dx + dy * dy);
37
+ if (len > maxLen) {
38
+ maxLen = len;
39
+ dirX = dx / len;
40
+ dirY = dy / len;
41
+ }
42
+ }
43
+ return { longSide: maxLen, dirX, dirY };
44
+ }
45
+ /** 从墙线段集合中估算地面高度 (Z 轴中位数) */
46
+ /** 基于窗户附近墙线段计算局部地面 Z(半径 3m) */
47
+ function computeLocalFloorZ(walls, cx, cy) {
48
+ const radius = 3;
49
+ const zs = [];
50
+ for (const w of walls) {
51
+ const mx = (w.start.x + w.end.x) / 2;
52
+ const my = (w.start.y + w.end.y) / 2;
53
+ const dx = mx - cx, dy = my - cy;
54
+ if (dx * dx + dy * dy <= radius * radius) {
55
+ zs.push(w.start.z, w.end.z);
56
+ }
57
+ }
58
+ if (zs.length === 0) {
59
+ // 附近无墙 → 回退到全局中位数
60
+ const allZ = [];
61
+ for (const w of walls)
62
+ allZ.push(w.start.z, w.end.z);
63
+ if (!allZ.length)
64
+ return -Infinity;
65
+ allZ.sort((a, b) => a - b);
66
+ return allZ[Math.floor(allZ.length / 2)];
67
+ }
68
+ zs.sort((a, b) => a - b);
69
+ return zs[Math.floor(zs.length / 2)];
70
+ }
71
+ /**
72
+ * 计算点 C 到线段 AB 的垂直距离与投影参数 t
73
+ * 返回 { dist, t },t ∈ [0,1] 表示垂足在线段上
74
+ */
75
+ function pointToSegmentDist(cx, cy, ax, ay, bx, by) {
76
+ const vx = bx - ax;
77
+ const vy = by - ay;
78
+ const len2 = vx * vx + vy * vy;
79
+ if (len2 < 1e-12) {
80
+ // 退化为点
81
+ return { dist: Math.sqrt((cx - ax) ** 2 + (cy - ay) ** 2), t: 0 };
82
+ }
83
+ const wx = cx - ax;
84
+ const wy = cy - ay;
85
+ const t = (wx * vx + wy * vy) / len2;
86
+ const projX = ax + t * vx;
87
+ const projY = ay + t * vy;
88
+ const dist = Math.sqrt((cx - projX) ** 2 + (cy - projY) ** 2);
89
+ return { dist, t };
90
+ }
91
+ /** 信号1:计算墙线段两端附近连接的其他墙数量 */
92
+ function scoreEndpointConnectivity(wall, allWalls, radius = 0.15) {
93
+ let left = 0;
94
+ let right = 0;
95
+ for (const other of allWalls) {
96
+ if (other === wall)
97
+ continue;
98
+ if (dist2D(wall.start, other.start) <= radius || dist2D(wall.start, other.end) <= radius)
99
+ left++;
100
+ if (dist2D(wall.end, other.start) <= radius || dist2D(wall.end, other.end) <= radius)
101
+ right++;
102
+ }
103
+ // 两端都有连接 = 5 分,一端有连接 = 2 分,两端自由 = 0 分
104
+ let score = 0;
105
+ if (left >= 1 && right >= 1)
106
+ score = 5;
107
+ else if (left >= 1 || right >= 1)
108
+ score = 2;
109
+ return { left, right, score };
110
+ }
111
+ /** 信号2:计算窗口5个检查点到墙线距离的方差(离散度越低越好) */
112
+ function scoreDistanceVariance(wall, checkPoints) {
113
+ const ds = [];
114
+ const { start, end } = wall;
115
+ for (const pt of checkPoints) {
116
+ const { dist } = pointToSegmentDist(pt.x, pt.y, start.x, start.y, end.x, end.y);
117
+ ds.push(dist);
118
+ }
119
+ const mean = ds.reduce((s, v) => s + v, 0) / ds.length;
120
+ const variance = ds.reduce((s, v) => s + (v - mean) ** 2, 0) / ds.length;
121
+ if (variance < 0.01)
122
+ return 3;
123
+ if (variance < 0.05)
124
+ return 2;
125
+ if (variance < 0.10)
126
+ return 1;
127
+ return 0;
128
+ }
129
+ /** 信号3:检查墙两端连接的垂直墙是否都向同一侧延伸 */
130
+ function scoreSameSidePerpendicular(wall, allWalls, connectRadius = 0.15) {
131
+ const dx = wall.end.x - wall.start.x;
132
+ const dy = wall.end.y - wall.start.y;
133
+ const len = Math.sqrt(dx * dx + dy * dy);
134
+ if (len < 1e-12)
135
+ return 0;
136
+ // 法线方向
137
+ const nx = -dy / len;
138
+ const ny = dx / len;
139
+ // 分别收集两端连接的垂直墙的"延伸侧"
140
+ const sidesByEnd = [[], []];
141
+ for (let ei = 0; ei < 2; ei++) {
142
+ const ep = ei === 0 ? wall.start : wall.end;
143
+ for (const other of allWalls) {
144
+ if (other === wall)
145
+ continue;
146
+ // 是否连接在此端点附近
147
+ const dStart = dist2D(ep, other.start);
148
+ const dEnd = dist2D(ep, other.end);
149
+ let farEnd = null;
150
+ if (dStart <= connectRadius)
151
+ farEnd = other.end;
152
+ else if (dEnd <= connectRadius)
153
+ farEnd = other.start;
154
+ if (!farEnd)
155
+ continue;
156
+ // 是否大致垂直于本墙(70°~110°)
157
+ const odx = other.end.x - other.start.x;
158
+ const ody = other.end.y - other.start.y;
159
+ const olen = Math.sqrt(odx * odx + ody * ody);
160
+ if (olen < 1e-12)
161
+ continue;
162
+ const dot = Math.abs(dx * odx + dy * ody) / (len * olen);
163
+ // 垂直墙的 dot 接近 0(余弦值 < cos70° ≈ 0.342)
164
+ if (dot >= 0.342)
165
+ continue;
166
+ // farEnd 在法线方向的哪一侧
167
+ const side = (farEnd.x - ep.x) * nx + (farEnd.y - ep.y) * ny;
168
+ sidesByEnd[ei].push(side > 0 ? 1 : -1);
169
+ }
170
+ }
171
+ // 两端都必须有垂直墙连接,且所有垂直墙的延伸方向一致
172
+ if (sidesByEnd[0].length === 0 || sidesByEnd[1].length === 0)
173
+ return 0;
174
+ const allSides = [...sidesByEnd[0], ...sidesByEnd[1]];
175
+ const allSame = allSides.every(s => s === allSides[0]);
176
+ return allSame ? 2 : 1;
177
+ }
178
+ /** 综合评分 */
179
+ function computeWallScore(wall, checkPoints, allWalls) {
180
+ const conn = scoreEndpointConnectivity(wall, allWalls);
181
+ const variance = scoreDistanceVariance(wall, checkPoints);
182
+ const sameSide = scoreSameSidePerpendicular(wall, allWalls);
183
+ const score = conn.score * 3 + variance * 2 + sameSide * 2;
184
+ return { score, details: { conn: conn.score, variance, sameSide } };
185
+ }
186
+ /**
187
+ * 合并共线且相邻的墙线段
188
+ *
189
+ * 思路:
190
+ * 1. 将每条线段的方向无向化到 [0°, 180°),按角度分桶(±5° 容差)
191
+ * 2. 每个桶内计算线段到参考线的垂直距离,进一步按共线关系分组
192
+ * 3. 每组内投影到方向轴上,合并重叠/相邻的区间
193
+ *
194
+ * @param segments 原始墙线段列表
195
+ * @param angleTol 角度容差 (°),默认 5
196
+ * @param gapTol 间隙容差 (m),默认 0.05,小于此值的间隙视为相连
197
+ * @returns 合并后的墙线段列表
198
+ */
199
+ function mergeCollinearSegments(segments, angleTol = 5, gapTol = 0.05) {
200
+ if (segments.length <= 1)
201
+ return { segments, sourceMap: segments.map((_, i) => [i]) };
202
+ const items = segments.map((seg, idx) => {
203
+ const dx = seg.end.x - seg.start.x, dy = seg.end.y - seg.start.y;
204
+ let angle = Math.atan2(dy, dx) * (180 / Math.PI);
205
+ if (angle < 0)
206
+ angle += 180;
207
+ return { seg, angle, idx };
208
+ });
209
+ items.sort((a, b) => a.angle - b.angle);
210
+ const buckets = [];
211
+ for (const item of items) {
212
+ let placed = false;
213
+ for (const bucket of buckets) {
214
+ const d = Math.abs(item.angle - bucket[0].angle);
215
+ if (Math.min(d, 180 - d) <= angleTol) {
216
+ bucket.push(item);
217
+ placed = true;
218
+ break;
219
+ }
220
+ }
221
+ if (!placed)
222
+ buckets.push([item]);
223
+ }
224
+ const mergedSegs = [];
225
+ const mergedSources = [];
226
+ const debugRPZGroups = [];
227
+ for (const bucket of buckets) {
228
+ let ref = bucket[0].seg, refMaxLen = 0;
229
+ for (const item of bucket)
230
+ if (item.seg.length > refMaxLen) {
231
+ refMaxLen = item.seg.length;
232
+ ref = item.seg;
233
+ }
234
+ const rDx = ref.end.x - ref.start.x, rDy = ref.end.y - ref.start.y;
235
+ const rLen = Math.sqrt(rDx * rDx + rDy * rDy);
236
+ if (rLen < 1e-12)
237
+ continue;
238
+ const nx = -rDy / rLen, ny = rDx / rLen;
239
+ const withOffset = bucket.map((item) => {
240
+ const dx = item.seg.start.x - ref.start.x, dy = item.seg.start.y - ref.start.y;
241
+ return { seg: item.seg, offset: Math.abs(dx * nx + dy * ny), idx: item.idx };
242
+ });
243
+ withOffset.sort((a, b) => a.offset - b.offset);
244
+ const collinearGroups = [];
245
+ for (const item of withOffset) {
246
+ let placed = false;
247
+ for (const g of collinearGroups) {
248
+ if (Math.abs(item.offset - g[0].offset) <= 0.05) {
249
+ g.push(item);
250
+ placed = true;
251
+ break;
252
+ }
253
+ }
254
+ if (!placed)
255
+ collinearGroups.push([item]);
256
+ }
257
+ for (const group of collinearGroups) {
258
+ let gref = group[0].seg, grefLen = 0;
259
+ for (const gi of group)
260
+ if (gi.seg.length > grefLen) {
261
+ grefLen = gi.seg.length;
262
+ gref = gi.seg;
263
+ }
264
+ const gDx = gref.end.x - gref.start.x, gDy = gref.end.y - gref.start.y;
265
+ const gLen = Math.sqrt(gDx * gDx + gDy * gDy);
266
+ if (gLen < 1e-12)
267
+ continue;
268
+ const dirX = gDx / gLen, dirY = gDy / gLen;
269
+ // --- rooftopPz: 取组内最大值合并 ---
270
+ const rpzVals = group.map(gi => gi.seg.rooftopPz ?? 0);
271
+ const maxRpz = Math.max(...rpzVals);
272
+ const rpzSet = [...new Set(rpzVals.map(v => v.toFixed(3)))];
273
+ if (rpzSet.length > 1) {
274
+ console.warn("[merge] inconsistent rooftopPz:", rpzSet.join("/"), "max=", maxRpz.toFixed(3), "count=", group.length);
275
+ const rpzSegs = group.map(gi => ({ idx: gi.idx, start: { x: gi.seg.start.x, y: gi.seg.start.y, z: gi.seg.start.z }, end: { x: gi.seg.end.x, y: gi.seg.end.y, z: gi.seg.end.z }, length: gi.seg.length, rooftopPz: gi.seg.rooftopPz ?? 0 }));
276
+ debugRPZGroups.push({ values: [...rpzSet], segments: rpzSegs });
277
+ console.log("[debugRPZ] " + JSON.stringify(rpzSegs));
278
+ }
279
+ const rooftopPz = maxRpz;
280
+ // --- buildRosource source check ---
281
+ const srcSet = [...new Set(group.map(gi => String(gi.seg.buildRosource)))];
282
+ if (srcSet.length > 1 && group.length > 1)
283
+ console.warn("[merge] buildRosource src:", srcSet.join("/"));
284
+ const buildRosource = gref.buildRosource;
285
+ // --- collect intervals (geometry only) ---
286
+ const intervals = [];
287
+ const srcIdxs = [];
288
+ for (const gi of group) {
289
+ const s = gi.seg;
290
+ const t1 = (s.start.x - gref.start.x) * dirX + (s.start.y - gref.start.y) * dirY;
291
+ const t2 = (s.end.x - gref.start.x) * dirX + (s.end.y - gref.start.y) * dirY;
292
+ intervals.push([Math.min(t1, t2), Math.max(t1, t2)]);
293
+ srcIdxs.push(gi.idx);
294
+ }
295
+ intervals.sort((a, b) => a[0] - b[0]);
296
+ const mergedIntervals = [];
297
+ for (const [l, r] of intervals) {
298
+ if (mergedIntervals.length === 0) {
299
+ mergedIntervals.push([l, r]);
300
+ continue;
301
+ }
302
+ const last = mergedIntervals[mergedIntervals.length - 1];
303
+ if (l <= last[1] + gapTol)
304
+ last[1] = Math.max(last[1], r);
305
+ else
306
+ mergedIntervals.push([l, r]);
307
+ }
308
+ for (const [l, r] of mergedIntervals) {
309
+ const len = r - l;
310
+ if (len < 0.01)
311
+ continue;
312
+ // 从 gref 复制所有现有字段,然后只覆盖会变化的字段(几何、来源、状态等)
313
+ const newStart = { x: gref.start.x + l * dirX, y: gref.start.y + l * dirY, z: gref.start.z };
314
+ const newEnd = { x: gref.start.x + r * dirX, y: gref.start.y + r * dirY, z: gref.start.z };
315
+ // 把 gref 的所有字段复制过来,再覆盖会变化的字段
316
+ const base = { ...gref };
317
+ base.start = newStart;
318
+ base.end = newEnd;
319
+ base.length = len;
320
+ base.direction = { x: dirX, y: dirY, z: 0 };
321
+ base.rooftopPz = rooftopPz;
322
+ base.buildRosource = buildRosource;
323
+ base.isRebuild = false;
324
+ // points / boxData / originalPoints / doorAndBeamData / insetionArr 保留 gref 的原值
325
+ // 如果 doorAndBeamData 或 insetionArr 在 gref 中不存在,则设为 []
326
+ if (!base.doorAndBeamData)
327
+ base.doorAndBeamData = [];
328
+ if (!base.insetionArr)
329
+ base.insetionArr = [];
330
+ mergedSegs.push(base);
331
+ mergedSources.push(srcIdxs);
332
+ }
333
+ }
334
+ }
335
+ // --- Step 5: endpoint join ---
336
+ let changed = true;
337
+ while (changed) {
338
+ changed = false;
339
+ for (let i = 0; i < mergedSegs.length; i++) {
340
+ for (let j = i + 1; j < mergedSegs.length; j++) {
341
+ const a = mergedSegs[i], b = mergedSegs[j];
342
+ if (a.rooftopPz !== undefined && b.rooftopPz !== undefined)
343
+ if (Math.abs(a.rooftopPz - b.rooftopPz) > 0.05)
344
+ continue;
345
+ const s1 = Math.abs(a.end.x - b.start.x) < 0.001 && Math.abs(a.end.y - b.start.y) < 0.001;
346
+ const s2 = Math.abs(a.start.x - b.end.x) < 0.001 && Math.abs(a.start.y - b.end.y) < 0.001;
347
+ const s3 = Math.abs(a.end.x - b.end.x) < 0.001 && Math.abs(a.end.y - b.end.y) < 0.001;
348
+ const s4 = Math.abs(a.start.x - b.start.x) < 0.001 && Math.abs(a.start.y - b.start.y) < 0.001;
349
+ if (!(s1 || s2 || s3 || s4))
350
+ continue;
351
+ const dot = a.direction.x * b.direction.x + a.direction.y * b.direction.y;
352
+ if (dot < 0.98)
353
+ continue;
354
+ let ns = a.start, ne = a.end;
355
+ if (s1)
356
+ ne = b.end;
357
+ else if (s2)
358
+ ns = b.start;
359
+ else if (s3)
360
+ ne = b.start;
361
+ else if (s4)
362
+ ns = b.end;
363
+ const nl = Math.hypot(ne.x - ns.x, ne.y - ns.y);
364
+ // 从 a 复制所有字段,只覆盖会变化的字段
365
+ const mergedBase = { ...a };
366
+ mergedBase.start = ns;
367
+ mergedBase.end = ne;
368
+ mergedBase.length = nl;
369
+ mergedBase.direction = { x: (ne.x - ns.x) / nl, y: (ne.y - ns.y) / nl, z: 0 };
370
+ mergedBase.rooftopPz = a.rooftopPz !== undefined ? a.rooftopPz : b.rooftopPz;
371
+ mergedBase.buildRosource = a.buildRosource || b.buildRosource;
372
+ mergedBase.isRebuild = false;
373
+ // 保留 a 的 points / boxData / originalPoints / doorAndBeamData / insetionArr
374
+ if (!mergedBase.doorAndBeamData)
375
+ mergedBase.doorAndBeamData = [];
376
+ if (!mergedBase.insetionArr)
377
+ mergedBase.insetionArr = [];
378
+ mergedSegs[i] = mergedBase;
379
+ mergedSources[i] = [...new Set([...mergedSources[i], ...mergedSources[j]])];
380
+ mergedSegs.splice(j, 1);
381
+ mergedSources.splice(j, 1);
382
+ j--;
383
+ changed = true;
384
+ }
385
+ }
386
+ }
387
+ return { segments: mergedSegs, sourceMap: mergedSources, debugRPZGroups };
388
+ }
389
+ function findWindowWalls(windowObjs, wallSegments, options) {
390
+ const opts = {
391
+ minLengthRatio: 0.95,
392
+ maxDistance: 0.5,
393
+ angleThreshold: 45,
394
+ projectionMargin: 0.1,
395
+ printOnly: true,
396
+ ...options,
397
+ };
398
+ const results = [];
399
+ // ---- Step 0: 共线合并墙线段 ----
400
+ const { segments: mergedSegments, sourceMap: mergeSourceMap } = mergeCollinearSegments(wallSegments);
401
+ console.log(`[findWindowWall] 墙线段共线合并: ${wallSegments.length} → ${mergedSegments.length} 条`);
402
+ // 合并线段 + 原始线段共同作为候选
403
+ // - 合并线段:覆盖多段小线段拼成的长墙场景
404
+ // - 原始线段:当合并引入微小偏差时,原始线段保底
405
+ const candidateSegments = [...mergedSegments, ...wallSegments];
406
+ for (const win of windowObjs) {
407
+ // ---- Step 0: 解析窗户四边形 ----
408
+ const coords = win.coordinatesByArea?.coordinates;
409
+ if (!coords || coords.length < 4) {
410
+ console.warn(`[findWindowWall] ${win.name} 缺少 coordinatesByArea.coordinates,跳过`);
411
+ continue;
412
+ }
413
+ const corners = coords.slice(0, 4);
414
+ const centerX = corners.reduce((s, p) => s + p.x, 0) / 4;
415
+ const centerY = corners.reduce((s, p) => s + p.y, 0) / 4;
416
+ const { longSide: winLong, dirX: winDirX, dirY: winDirY } = analyzeQuad(corners);
417
+ if (winLong < 0.01) {
418
+ console.warn(`[findWindowWall] ${win.name} 四边形边长过短 (${winLong.toFixed(3)}),跳过`);
419
+ continue;
420
+ }
421
+ // ---- 高度校验:基于附近墙段的局部地面 Z ----
422
+ const quadZ = corners.reduce((s, p) => s + p.z, 0) / 4;
423
+ const floorZ = computeLocalFloorZ(wallSegments, centerX, centerY);
424
+ if (quadZ < floorZ - 0.3) {
425
+ console.warn(`[findWindowWall] ${win.name} 高度异常(z=${quadZ.toFixed(3)},附近地面=${floorZ.toFixed(3)}),跳过`);
426
+ continue;
427
+ }
428
+ // ---- Step 1-2: 收集候选墙线段 → 多信号评分择优 ----
429
+ let bestSeg = null;
430
+ // 收集窗户的 5 个检查点(中心 + 4 角点)
431
+ // 解决窗户偏在墙的一端时中心投影越界的问题
432
+ const checkPoints = [
433
+ { x: centerX, y: centerY, z: 0 }, // 中心点
434
+ { x: corners[0].x, y: corners[0].y, z: 0 }, // 4 个角点
435
+ { x: corners[1].x, y: corners[1].y, z: 0 },
436
+ { x: corners[2].x, y: corners[2].y, z: 0 },
437
+ { x: corners[3].x, y: corners[3].y, z: 0 },
438
+ ];
439
+ // 扫查日志:打印候选墙线段详情,用于排查未匹配或匹配偏差的问题
440
+ if (win.name.includes('_008') || win.name.includes('_002') ||
441
+ win.name.includes('_014') || win.name.includes('_015') || win.name.includes('_020')) {
442
+ const allScored = candidateSegments.map((seg) => {
443
+ const { start, end } = seg;
444
+ // 中心点到无限直线的距离
445
+ const lineDist = pointToSegmentDist(centerX, centerY, start.x, start.y, end.x, end.y);
446
+ // 5 个点的投影数据
447
+ const pts = checkPoints.map((pt) => {
448
+ const r = pointToSegmentDist(pt.x, pt.y, start.x, start.y, end.x, end.y);
449
+ return `t=${r.t.toFixed(3)},d=${r.dist.toFixed(3)}`;
450
+ });
451
+ // 方向角
452
+ const dx = end.x - start.x, dy = end.y - start.y;
453
+ const sl = Math.sqrt(dx * dx + dy * dy) || 1;
454
+ const sdx = dx / sl, sdy = dy / sl;
455
+ const dot = Math.abs(winDirX * sdx + winDirY * sdy);
456
+ const ang = Math.acos(Math.min(dot, 1)) * (180 / Math.PI);
457
+ return { seg, lineDist: lineDist.dist, t: lineDist.t, pts, angle: ang, length: seg.length };
458
+ });
459
+ allScored.sort((a, b) => a.lineDist - b.lineDist);
460
+ // 打印该窗户的全称
461
+ console.warn(`[${win.name}扫查] 按无限直线距离排序的前 15 条候选: (需长≥${(winLong * opts.minLengthRatio).toFixed(2)})`);
462
+ for (let i = 0; i < Math.min(15, allScored.length); i++) {
463
+ const s = allScored[i];
464
+ const lenOk = s.length >= winLong * opts.minLengthRatio ? '✓' : `✗(需${(winLong * opts.minLengthRatio).toFixed(2)})`;
465
+ const tOk = Math.abs(s.t) <= 1 + 0.4 ? '✓' : '✗'; // 宽松 t check
466
+ const dOk = s.lineDist <= 0.65 ? '✓' : '✗'; // 宽松 d check
467
+ const aOk = s.angle <= 45 ? '✓' : '✗';
468
+ console.warn(` #${i} 距=${s.lineDist.toFixed(3)}m t=${s.t.toFixed(3)} 角=${s.angle.toFixed(1)}° 长=${s.length.toFixed(3)}m` +
469
+ ` [长度${lenOk} 投影${tOk} 距离${dOk} 角度${aOk}]` +
470
+ ` 起点(${s.seg.start.x.toFixed(3)},${s.seg.start.y.toFixed(3)})→(${s.seg.end.x.toFixed(3)},${s.seg.end.y.toFixed(3)})` +
471
+ ` | 5点: ${s.pts.join(' | ')}`);
472
+ }
473
+ }
474
+ // ---- 多信号评分匹配:收集候选 → 评分 → 择优 ----
475
+ // 解决当窗户位于内外两墙之间时,优先选择外墙的问题
476
+ const matchAttempts = [
477
+ { margin: opts.projectionMargin, maxDist: opts.maxDistance, label: '严格' },
478
+ { margin: 0.4, maxDist: 0.65, label: '宽松' },
479
+ ];
480
+ let passingCandidates = [];
481
+ for (const attempt of matchAttempts) {
482
+ // 如果上一轮已有候选,不再尝试宽松参数
483
+ if (passingCandidates.length > 0)
484
+ break;
485
+ for (const seg of candidateSegments) {
486
+ // 粗筛:长度
487
+ if (seg.length < winLong * opts.minLengthRatio)
488
+ continue;
489
+ const { start, end } = seg;
490
+ // 检查 5 个点中是否有任意一个通过投影 + 距离检查
491
+ let validPoint = false;
492
+ let minDist = Infinity;
493
+ for (const pt of checkPoints) {
494
+ const { dist, t } = pointToSegmentDist(pt.x, pt.y, start.x, start.y, end.x, end.y);
495
+ if (t >= -attempt.margin && t <= 1 + attempt.margin && dist <= attempt.maxDist) {
496
+ validPoint = true;
497
+ minDist = Math.min(minDist, dist);
498
+ }
499
+ }
500
+ if (!validPoint)
501
+ continue;
502
+ // 方向约束:墙线方向与窗户长边方向的夹角
503
+ const segLen = Math.sqrt((end.x - start.x) ** 2 + (end.y - start.y) ** 2);
504
+ if (segLen < 1e-12)
505
+ continue;
506
+ const segDirX = (end.x - start.x) / segLen;
507
+ const segDirY = (end.y - start.y) / segLen;
508
+ const dot = Math.abs(winDirX * segDirX + winDirY * segDirY);
509
+ const angle = Math.acos(Math.min(dot, 1)) * (180 / Math.PI);
510
+ if (angle > opts.angleThreshold)
511
+ continue;
512
+ // 通过所有基础检查,加入候选列表
513
+ passingCandidates.push({
514
+ seg,
515
+ minDist,
516
+ ratio: seg.length / winLong,
517
+ score: 0,
518
+ details: { conn: 0, variance: 0, sameSide: 0 },
519
+ });
520
+ }
521
+ if (passingCandidates.length > 0) {
522
+ console.log(`[findWindowWall] ${win.name} ${attempt.label}模式: 有 ${passingCandidates.length} 条候选`);
523
+ }
524
+ }
525
+ // 多信号评分
526
+ if (passingCandidates.length > 1) {
527
+ for (const pc of passingCandidates) {
528
+ const { score, details } = computeWallScore(pc.seg, checkPoints, wallSegments);
529
+ pc.score = score;
530
+ pc.details = details;
531
+ }
532
+ // 按评分降序,同分按距离升序
533
+ passingCandidates.sort((a, b) => b.score - a.score || a.minDist - b.minDist);
534
+ const best = passingCandidates[0];
535
+ const logDetail = passingCandidates.map(p => `评分=${p.score}(conn=${p.details.conn}/var=${p.details.variance}/side=${p.details.sameSide}) dist=${p.minDist.toFixed(3)}`).join(' | ');
536
+ console.log(`[findWindowWall] ${win.name} 评分排序: ${logDetail}`);
537
+ console.log(`[findWindowWall] ${win.name} → 选中评分=${best.score}(conn=${best.details.conn}/var=${best.details.variance}/side=${best.details.sameSide}) dist=${best.minDist.toFixed(3)}m`);
538
+ }
539
+ else if (passingCandidates.length === 1) {
540
+ passingCandidates[0].score = -1; // 仅一条候选,不评分
541
+ }
542
+ let bestDist = Infinity;
543
+ let bestRatio = 0;
544
+ if (passingCandidates.length > 0) {
545
+ const winner = passingCandidates[0];
546
+ bestSeg = winner.seg;
547
+ bestDist = winner.minDist;
548
+ bestRatio = winner.ratio;
549
+ }
550
+ // 临时:输出 008 的匹配结果供验证
551
+ if (win.name.includes('_008') && bestSeg) {
552
+ console.log(`[findWindowWall] ${win.name} 匹配墙线: (${bestSeg.start.x.toFixed(3)},${bestSeg.start.y.toFixed(3)})→(${bestSeg.end.x.toFixed(3)},${bestSeg.end.y.toFixed(3)}) len=${bestSeg.length.toFixed(3)}m dist=${bestDist.toFixed(3)}m`);
553
+ }
554
+ // ---- drawWindow 计算(仅打印模式,默认不写入)----
555
+ // printOnly=true 时只打印匹配的 "窗户-墙段" 组,以及最终合成后的 drawWindow 结构
556
+ // printOnly=false 时才真正写入 wallSegment.drawWindow
557
+ let dw_info = undefined;
558
+ if (bestSeg) {
559
+ const dw_dx = bestSeg.end.x - bestSeg.start.x;
560
+ const dw_dy = bestSeg.end.y - bestSeg.start.y;
561
+ const dw_segLen = Math.sqrt(dw_dx * dw_dx + dw_dy * dw_dy);
562
+ const dw_dirX = dw_dx / dw_segLen;
563
+ const dw_dirY = dw_dy / dw_segLen;
564
+ // 将窗户 4 角点投影到墙段的参数轴上,得到 t∈[0,1] 的区间
565
+ const dw_tVals = [];
566
+ for (let ci = 0; ci < corners.length; ci++) {
567
+ const dw_px = corners[ci].x - bestSeg.start.x;
568
+ const dw_py = corners[ci].y - bestSeg.start.y;
569
+ const dw_t = (dw_px * dw_dirX + dw_py * dw_dirY) / dw_segLen;
570
+ dw_tVals.push(dw_t);
571
+ }
572
+ const dw_tMin = Math.min(...dw_tVals);
573
+ const dw_tMax = Math.max(...dw_tVals);
574
+ const dw_width = (dw_tMax - dw_tMin) * dw_segLen;
575
+ const dw_midT = (dw_tMin + dw_tMax) / 2;
576
+ const dw_pMidX = bestSeg.start.x + dw_midT * dw_dx;
577
+ const dw_pMidY = bestSeg.start.y + dw_midT * dw_dy;
578
+ const dw_boxMinZ = win.box.min.z;
579
+ const dw_boxMaxZ = win.box.max.z;
580
+ const dw_height = Math.abs(dw_boxMaxZ - dw_boxMinZ);
581
+ const dw_floorZ = computeLocalFloorZ(mergedSegments, bestSeg.start.x, bestSeg.start.y);
582
+ const dw_gClr = Math.max(0, dw_boxMinZ - dw_floorZ);
583
+ const dw_full = dw_tMin <= 0 && dw_tMax >= 1;
584
+ dw_info = {
585
+ p: { x: dw_pMidX, y: dw_pMidY, z: dw_boxMinZ + dw_height / 2 },
586
+ width: dw_width,
587
+ full: dw_full,
588
+ height: dw_height,
589
+ groundClearance: dw_gClr,
590
+ };
591
+ // ===== 打印 drawWindow 数据 =====
592
+ console.log('[drawWindow]', win.name, JSON.stringify(dw_info));
593
+ if (!opts.printOnly) {
594
+ const bs = bestSeg;
595
+ if (!bs.drawWindow)
596
+ bs.drawWindow = [];
597
+ bs.drawWindow.push(dw_info);
598
+ }
599
+ }
600
+ // ---- Step 3: 输出 ----
601
+ if (bestSeg) {
602
+ results.push({
603
+ windowName: win.name,
604
+ windowCategory: win.category,
605
+ windowCenter: win.center,
606
+ wallSegment: bestSeg,
607
+ distance: bestDist,
608
+ wallLengthRatio: bestRatio,
609
+ drawWindow: dw_info,
610
+ });
611
+ }
612
+ else {
613
+ console.warn(`[findWindowWall] ${win.name} 未找到匹配的墙线段`);
614
+ }
615
+ }
616
+ // ---- Step 4: 数据合并(只对匹配上的墙段做)----
617
+ // 遍历匹配结果,如果墙段来自合并线段,则从原始线段中收集数据字段
618
+ for (const r of results) {
619
+ const ws = r.wallSegment;
620
+ // 找到 ws 在 mergedSegments 中的索引
621
+ const mi = mergedSegments.indexOf(ws);
622
+ if (mi === -1)
623
+ continue; // 不是合并线段(是原始线段),跳过
624
+ const srcIdxs = mergeSourceMap[mi];
625
+ if (!srcIdxs || srcIdxs.length <= 1)
626
+ continue; // 没有可合并的源数据
627
+ const srcSegs = srcIdxs.map((idx) => wallSegments[idx]);
628
+ // 合并数据字段
629
+ const allPoints = [];
630
+ const allOrig = [];
631
+ const allDoor = [];
632
+ const allInsetion = [];
633
+ const allDrawWin = [];
634
+ let boxData = undefined;
635
+ for (const s of srcSegs) {
636
+ if (s.points?.length)
637
+ for (const p of s.points)
638
+ allPoints.push(p);
639
+ if (s.originalPoints?.length)
640
+ for (const p of s.originalPoints)
641
+ allOrig.push(p);
642
+ if (s.doorAndBeamData?.length)
643
+ for (const p of s.doorAndBeamData)
644
+ allDoor.push(p);
645
+ if (s.insetionArr?.length)
646
+ for (const p of s.insetionArr)
647
+ allInsetion.push(p);
648
+ if (s.drawWindow?.length)
649
+ for (const p of s.drawWindow)
650
+ allDrawWin.push(p);
651
+ if (s.boxData && !boxData)
652
+ boxData = s.boxData;
653
+ }
654
+ if (allPoints.length)
655
+ ws.points = allPoints;
656
+ if (allOrig.length)
657
+ ws.originalPoints = allOrig;
658
+ if (allDoor.length)
659
+ ws.doorAndBeamData = allDoor;
660
+ if (allInsetion.length)
661
+ ws.insetionArr = allInsetion;
662
+ if (allDrawWin.length)
663
+ ws.drawWindow = allDrawWin;
664
+ if (boxData)
665
+ ws.boxData = boxData;
666
+ if (allDrawWin.length > 0) {
667
+ console.log('[dataMerge] wall (' + ws.start.x.toFixed(3) + ',' + ws.start.y.toFixed(3) + ')->(' +
668
+ ws.end.x.toFixed(3) + ',' + ws.end.y.toFixed(3) + ')' +
669
+ ' merged from ' + srcIdxs.length + ' segments' +
670
+ ' drawWindow=' + allDrawWin.length + ' items');
671
+ }
672
+ }
673
+ // ---- Step 5: 打印合并后的 drawWindow(核对用,不影响业务输出)----
674
+ // 只打印合并后仍携带 drawWindow 的那段墙,便于人工核对窗-墙对应关系
675
+ const hasDw = mergedSegments.filter((s) => s.drawWindow && s.drawWindow.length > 0);
676
+ if (hasDw.length > 0) {
677
+ console.log('[findWindowWall] 合并后携带 drawWindow 的墙段数量=' + hasDw.length);
678
+ for (const s of hasDw) {
679
+ console.log('[findWindowWall] 墙段: (' + s.start.x.toFixed(3) + ',' + s.start.y.toFixed(3) + ')->(' +
680
+ s.end.x.toFixed(3) + ',' + s.end.y.toFixed(3) + ') len=' + s.length.toFixed(3) + 'm' +
681
+ ' rooftopPz=' + (s.rooftopPz !== undefined ? s.rooftopPz.toFixed(3) : 'N/A'));
682
+ const dw = s.drawWindow;
683
+ for (let i = 0; i < dw.length; i++) {
684
+ const dwItem = dw[i];
685
+ console.log(' [drawWindow #' + i + '] p=(' + dwItem.p.x.toFixed(3) + ',' + dwItem.p.y.toFixed(3) +
686
+ ') width=' + dwItem.width.toFixed(3) + 'm height=' + dwItem.height.toFixed(3) +
687
+ 'm groundClearance=' + dwItem.groundClearance.toFixed(3) + 'm full=' + dwItem.full);
688
+ }
689
+ }
690
+ }
691
+ return results;
692
+ }
693
+ //# sourceMappingURL=findWindowWall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findWindowWall.js","sourceRoot":"","sources":["../src/findWindowWall.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;AA6GH,wBAIC;AAGD,kCAmBC;AAID,gDAqBC;AAMD,gDAmBC;AAwID,wDA0H8E;AAE9E,0CA0UC;AA7pBD,iBAAiB;AAEjB,oBAAoB;AACpB,SAAgB,MAAM,CAAC,CAAU,EAAE,CAAU;IAC3C,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IACpB,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IACpB,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAA;AACrC,CAAC;AAED,2BAA2B;AAC3B,SAAgB,WAAW,CAAC,OAAkB;IAC5C,IAAI,MAAM,GAAG,CAAC,CAAA;IACd,IAAI,IAAI,GAAG,CAAC,CAAA;IACZ,IAAI,IAAI,GAAG,CAAC,CAAA;IAEZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;QACpB,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;QAC9B,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;QACpB,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;QACpB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAA;QACxC,IAAI,GAAG,GAAG,MAAM,EAAE,CAAC;YACjB,MAAM,GAAG,GAAG,CAAA;YACZ,IAAI,GAAG,EAAE,GAAG,GAAG,CAAA;YACf,IAAI,GAAG,EAAE,GAAG,GAAG,CAAA;QACjB,CAAC;IACH,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;AACzC,CAAC;AAED,6BAA6B;AAC7B,+BAA+B;AAC/B,SAAgB,kBAAkB,CAAC,KAAoB,EAAE,EAAU,EAAE,EAAU;IAC7E,MAAM,MAAM,GAAG,CAAC,CAAA;IAChB,MAAM,EAAE,GAAa,EAAE,CAAA;IACvB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;QACpC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;QACpC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;QAChC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,MAAM,GAAG,MAAM,EAAE,CAAC;YACzC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;QAC7B,CAAC;IACH,CAAC;IACD,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpB,kBAAkB;QAClB,MAAM,IAAI,GAAa,EAAE,CAAA;QACzB,KAAK,MAAM,CAAC,IAAI,KAAK;YAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;QACpD,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO,CAAC,QAAQ,CAAA;QAClC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;QAC1B,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAA;IAC1C,CAAC;IACD,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IACxB,OAAO,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAA;AACtC,CAAC;AAED;;;GAGG;AACH,SAAgB,kBAAkB,CAChC,EAAU,EAAE,EAAU,EACtB,EAAU,EAAE,EAAU,EACtB,EAAU,EAAE,EAAU;IAEtB,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;IAClB,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;IAClB,MAAM,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;IAC9B,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC;QACjB,OAAO;QACP,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAA;IACnE,CAAC;IACD,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;IAClB,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;IAClB,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,IAAI,CAAA;IACpC,MAAM,KAAK,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAA;IACzB,MAAM,KAAK,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAA;IACzB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAA;IAC7D,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,CAAA;AACpB,CAAC;AAmBD,4BAA4B;AAC5B,SAAS,yBAAyB,CAChC,IAAiB,EACjB,QAAuB,EACvB,MAAM,GAAG,IAAI;IAEb,IAAI,IAAI,GAAG,CAAC,CAAA;IACZ,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QAC7B,IAAI,KAAK,KAAK,IAAI;YAAE,SAAQ;QAC5B,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,MAAM;YAAE,IAAI,EAAE,CAAA;QAChG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,MAAM;YAAE,KAAK,EAAE,CAAA;IAC/F,CAAC;IACD,sCAAsC;IACtC,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC;QAAE,KAAK,GAAG,CAAC,CAAA;SACjC,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC;QAAE,KAAK,GAAG,CAAC,CAAA;IAC3C,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;AAC/B,CAAC;AAED,qCAAqC;AACrC,SAAS,qBAAqB,CAC5B,IAAiB,EACjB,WAAsB;IAEtB,MAAM,EAAE,GAAa,EAAE,CAAA;IACvB,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;IAC3B,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;QAC7B,MAAM,EAAE,IAAI,EAAE,GAAG,kBAAkB,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;QAC/E,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACf,CAAC;IACD,MAAM,IAAI,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,MAAM,CAAA;IACtD,MAAM,QAAQ,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,MAAM,CAAA;IACxE,IAAI,QAAQ,GAAG,IAAI;QAAE,OAAO,CAAC,CAAA;IAC7B,IAAI,QAAQ,GAAG,IAAI;QAAE,OAAO,CAAC,CAAA;IAC7B,IAAI,QAAQ,GAAG,IAAI;QAAE,OAAO,CAAC,CAAA;IAC7B,OAAO,CAAC,CAAA;AACV,CAAC;AAED,+BAA+B;AAC/B,SAAS,0BAA0B,CACjC,IAAiB,EACjB,QAAuB,EACvB,aAAa,GAAG,IAAI;IAEpB,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAA;IACpC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAA;IACpC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAA;IACxC,IAAI,GAAG,GAAG,KAAK;QAAE,OAAO,CAAC,CAAA;IACzB,OAAO;IACP,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,GAAG,CAAA;IACpB,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,CAAA;IAEnB,qBAAqB;IACrB,MAAM,UAAU,GAAyB,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;IAEjD,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC;QAC9B,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAA;QAC3C,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;YAC7B,IAAI,KAAK,KAAK,IAAI;gBAAE,SAAQ;YAC5B,aAAa;YACb,MAAM,MAAM,GAAG,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,CAAA;YACtC,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,GAAG,CAAC,CAAA;YAClC,IAAI,MAAM,GAAmB,IAAI,CAAA;YACjC,IAAI,MAAM,IAAI,aAAa;gBAAE,MAAM,GAAG,KAAK,CAAC,GAAG,CAAA;iBAC1C,IAAI,IAAI,IAAI,aAAa;gBAAE,MAAM,GAAG,KAAK,CAAC,KAAK,CAAA;YACpD,IAAI,CAAC,MAAM;gBAAE,SAAQ;YAErB,sBAAsB;YACtB,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAA;YACvC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAA;YACvC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAA;YAC7C,IAAI,IAAI,GAAG,KAAK;gBAAE,SAAQ;YAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,GAAG,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,CAAA;YACxD,sCAAsC;YACtC,IAAI,GAAG,IAAI,KAAK;gBAAE,SAAQ;YAE1B,mBAAmB;YACnB,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAA;YAC5D,UAAU,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QACxC,CAAC;IACH,CAAC;IAED,4BAA4B;IAC5B,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAA;IACtE,MAAM,QAAQ,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAA;IACrD,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;IACtD,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AACxB,CAAC;AAED,WAAW;AACX,SAAS,gBAAgB,CACvB,IAAiB,EACjB,WAAsB,EACtB,QAAuB;IAEvB,MAAM,IAAI,GAAG,yBAAyB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;IACtD,MAAM,QAAQ,GAAG,qBAAqB,CAAC,IAAI,EAAE,WAAW,CAAC,CAAA;IACzD,MAAM,QAAQ,GAAG,0BAA0B,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;IAE3D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,GAAG,QAAQ,GAAG,CAAC,GAAG,QAAQ,GAAG,CAAC,CAAA;IAC1D,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,CAAA;AACrE,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAgB,sBAAsB,CACpC,QAAuB,EACvB,QAAQ,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI;IAC3B,IAAI,QAAQ,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAElG,MAAM,KAAK,GAAW,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC9C,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;QACjE,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;QAAC,IAAI,KAAK,GAAG,CAAC;YAAE,KAAK,IAAI,GAAG,CAAC;QAC9E,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;IAC7B,CAAC,CAAC,CAAC;IAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,MAAM,GAAG,KAAK,CAAC;QAAC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YACjD,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACjD,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,IAAI,QAAQ,EAAE,CAAC;gBAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAAC,MAAM,GAAG,IAAI,CAAC;gBAAC,MAAM;YAAC,CAAC;QACpF,CAAC;QAAC,IAAI,CAAC,MAAM;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAAC,CAAC;IACxC,MAAM,UAAU,GAAkB,EAAE,CAAC;IACrC,MAAM,aAAa,GAAe,EAAE,CAAC;IACrC,MAAM,cAAc,GAAoB,EAAE,CAAC;IAC3C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,SAAS,GAAG,CAAC,CAAC;QACvC,KAAK,MAAM,IAAI,IAAI,MAAM;YAAE,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;gBAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;gBAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;YAAC,CAAC;QAC5G,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;QACnE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;QAAC,IAAI,IAAI,GAAG,KAAK;YAAE,SAAS;QAC1E,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,IAAI,EAAE,EAAE,GAAG,GAAG,GAAG,IAAI,CAAC;QAExC,MAAM,UAAU,GAAgB,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YAClD,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;YAC/E,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC;QAC/E,CAAC,CAAC,CAAC;QAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;QACnD,MAAM,eAAe,GAAkB,EAAE,CAAC;QAC1C,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;YAC9B,IAAI,MAAM,GAAG,KAAK,CAAC;YAAC,KAAK,MAAM,CAAC,IAAI,eAAe,EAAE,CAAC;gBACpD,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;oBAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBAAC,MAAM,GAAG,IAAI,CAAC;oBAAC,MAAM;gBAAC,CAAC;YAC1F,CAAC;YAAC,IAAI,CAAC,MAAM;gBAAE,eAAe,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAAC,CAAC;QAChD,KAAK,MAAM,KAAK,IAAI,eAAe,EAAE,CAAC;YACpC,IAAI,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,OAAO,GAAG,CAAC,CAAC;YACrC,KAAK,MAAM,EAAE,IAAI,KAAK;gBAAE,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,GAAG,OAAO,EAAE,CAAC;oBAAC,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC;oBAAC,IAAI,GAAG,EAAE,CAAC,GAAG,CAAC;gBAAC,CAAC;YAChG,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YACvE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;YAAC,IAAI,IAAI,GAAG,KAAK;gBAAE,SAAS;YAC1E,MAAM,IAAI,GAAG,GAAG,GAAG,IAAI,EAAE,IAAI,GAAG,GAAG,GAAG,IAAI,CAAC;YAC3C,8BAA8B;YAC9B,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC;YACvD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC;YACpC,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5D,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtB,OAAO,CAAC,IAAI,CAAC,iCAAiC,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;gBACrH,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;gBAC5O,cAAc,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;gBAChE,OAAO,CAAC,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;YACvD,CAAC;YACD,MAAM,SAAS,GAAG,MAAM,CAAC;YACzB,qCAAqC;YACrC,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3E,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;gBAAE,OAAO,CAAC,IAAI,CAAC,4BAA4B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YACxG,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC;YACzC,4CAA4C;YAC5C,MAAM,SAAS,GAA4B,EAAE,CAAC;YAC9C,MAAM,OAAO,GAAa,EAAE,CAAC;YAC7B,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC;gBACvB,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC;gBACjB,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;gBACjF,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;gBAC7E,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;gBACrD,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;YAAC,CAAC;YACzB,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACtC,MAAM,eAAe,GAA4B,EAAE,CAAC;YACpD,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,SAAS,EAAE,CAAC;gBAC/B,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;oBAAC,SAAS;gBAAC,CAAC;gBAC7E,MAAM,IAAI,GAAG,eAAe,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBACzD,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,MAAM;oBAAE,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;;oBAAM,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAAC,CAAC;YACjG,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,eAAe,EAAE,CAAC;gBACrC,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;gBAAC,IAAI,GAAG,GAAG,IAAI;oBAAE,SAAS;gBAC5C,yCAAyC;gBACzC,MAAM,QAAQ,GAAG,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;gBAC7F,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;gBAC3F,6BAA6B;gBAC7B,MAAM,IAAI,GAAQ,EAAE,GAAG,IAAI,EAAE,CAAC;gBAC9B,IAAI,CAAC,KAAK,GAAG,QAAQ,CAAC;gBACtB,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC;gBAClB,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC;gBAClB,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;gBAC5C,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;gBAC3B,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;gBACnC,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;gBACvB,gFAAgF;gBAChF,sDAAsD;gBACtD,IAAI,CAAC,IAAI,CAAC,eAAe;oBAAE,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC;gBACrD,IAAI,CAAC,IAAI,CAAC,WAAW;oBAAE,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;gBAC7C,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACtB,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAAC,CAAC;QAAC,CAAC;IAAC,CAAC;IACxC,gCAAgC;IAChC,IAAI,OAAO,GAAG,IAAI,CAAC;IACnB,OAAO,OAAO,EAAE,CAAC;QAAC,OAAO,GAAG,KAAK,CAAC;QAChC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3C,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC/C,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;gBAC3C,IAAI,CAAC,CAAC,SAAS,KAAK,SAAS,IAAI,CAAC,CAAC,SAAS,KAAK,SAAS;oBAAE,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI;wBAAE,SAAS;gBACrH,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;gBAC1F,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;gBAC1F,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;gBACtF,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;gBAC9F,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;oBAAE,SAAS;gBACtC,MAAM,GAAG,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;gBAAC,IAAI,GAAG,GAAG,IAAI;oBAAE,SAAS;gBACpG,IAAI,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC;gBAC7B,IAAI,EAAE;oBAAE,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC;qBAAM,IAAI,EAAE;oBAAE,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC;qBAAM,IAAI,EAAE;oBAAE,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC;qBAAM,IAAI,EAAE;oBAAE,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC;gBAClG,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;gBAChD,uBAAuB;gBACvB,MAAM,UAAU,GAAQ,EAAE,GAAG,CAAC,EAAE,CAAC;gBACjC,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC;gBACtB,UAAU,CAAC,GAAG,GAAG,EAAE,CAAC;gBACpB,UAAU,CAAC,MAAM,GAAG,EAAE,CAAC;gBACvB,UAAU,CAAC,SAAS,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;gBAC9E,UAAU,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC7E,UAAU,CAAC,aAAa,GAAG,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC,aAAa,CAAC;gBAC9D,UAAU,CAAC,SAAS,GAAG,KAAK,CAAC;gBAC7B,2EAA2E;gBAC3E,IAAI,CAAC,UAAU,CAAC,eAAe;oBAAE,UAAU,CAAC,eAAe,GAAG,EAAE,CAAC;gBACjE,IAAI,CAAC,UAAU,CAAC,WAAW;oBAAE,UAAU,CAAC,WAAW,GAAG,EAAE,CAAC;gBACzD,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC;gBAC3B,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC5E,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;gBAAC,aAAa,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;gBAAC,CAAC,EAAE,CAAC;gBAAC,OAAO,GAAG,IAAI,CAAC;YAAC,CAAC;QAAC,CAAC;IAAC,CAAC;IACrF,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE,CAAC;AAAC,CAAC;AAE9E,SAAgB,eAAe,CAC7B,UAA0B,EAC1B,YAA2B,EAC3B,OAAyB;IAEzB,MAAM,IAAI,GAA8B;QACtC,cAAc,EAAE,IAAI;QACpB,WAAW,EAAE,GAAG;QAChB,cAAc,EAAE,EAAE;QAClB,gBAAgB,EAAE,GAAG;QACrB,SAAS,EAAE,IAAI;QACf,GAAG,OAAO;KACX,CAAA;IAED,MAAM,OAAO,GAAsB,EAAE,CAAA;IAErC,4BAA4B;IAC5B,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,sBAAsB,CAAC,YAAY,CAAC,CAAA;IACpG,OAAO,CAAC,GAAG,CACT,6BAA6B,YAAY,CAAC,MAAM,MAAM,cAAc,CAAC,MAAM,IAAI,CAChF,CAAA;IAED,oBAAoB;IACpB,0BAA0B;IAC1B,6BAA6B;IAC7B,MAAM,iBAAiB,GAAG,CAAC,GAAG,cAAc,EAAE,GAAG,YAAY,CAAC,CAAA;IAE9D,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,4BAA4B;QAC5B,MAAM,MAAM,GAAG,GAAG,CAAC,iBAAiB,EAAE,WAAW,CAAA;QACjD,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjC,OAAO,CAAC,IAAI,CAAC,oBAAoB,GAAG,CAAC,IAAI,sCAAsC,CAAC,CAAA;YAChF,SAAQ;QACV,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;QAClC,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAA;QACxD,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAA;QACxD,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,WAAW,CAAC,OAAO,CAAC,CAAA;QAEhF,IAAI,OAAO,GAAG,IAAI,EAAE,CAAC;YACnB,OAAO,CAAC,IAAI,CAAC,oBAAoB,GAAG,CAAC,IAAI,aAAa,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;YAC/E,SAAQ;QACV,CAAC;QAED,+BAA+B;QAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAA;QACtD,MAAM,MAAM,GAAG,kBAAkB,CAAC,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;QACjE,IAAI,KAAK,GAAG,MAAM,GAAG,GAAG,EAAE,CAAC;YACzB,OAAO,CAAC,IAAI,CAAC,oBAAoB,GAAG,CAAC,IAAI,WAAW,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;YACrG,SAAQ;QACV,CAAC;QAED,wCAAwC;QACxC,IAAI,OAAO,GAAuB,IAAI,CAAA;QAEtC,0BAA0B;QAC1B,uBAAuB;QACvB,MAAM,WAAW,GAAc;YAC7B,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,EAAiB,MAAM;YACvD,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAO,QAAQ;YACzD,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;YAC1C,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;YAC1C,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;SAC3C,CAAA;QAED,iCAAiC;QACjC,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;YACtD,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACxF,MAAM,SAAS,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;gBAC9C,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,GAAG,CAAA;gBAC1B,cAAc;gBACd,MAAM,QAAQ,GAAG,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;gBACrF,YAAY;gBACZ,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;oBACjC,MAAM,CAAC,GAAG,kBAAkB,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;oBACxE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA;gBACrD,CAAC,CAAC,CAAA;gBACF,MAAM;gBACN,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,EAAE,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAA;gBAChD,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;gBAC5C,MAAM,GAAG,GAAG,EAAE,GAAG,EAAE,EAAE,GAAG,GAAG,EAAE,GAAG,EAAE,CAAA;gBAClC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,GAAG,GAAG,OAAO,GAAG,GAAG,CAAC,CAAA;gBACnD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,CAAA;gBACzD,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAA;YAC7F,CAAC,CAAC,CAAA;YACF,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAA;YACjD,WAAW;YACX,OAAO,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,+BAA+B,CAAC,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;YACtG,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBACxD,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAA;gBACtB,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,IAAI,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAA;gBACnH,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAA,CAAC,aAAa;gBAC9D,MAAM,GAAG,GAAG,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAA,CAAQ,aAAa;gBAC/D,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAA;gBACrC,OAAO,CAAC,IAAI,CACV,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;oBAC5G,OAAO,KAAK,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,GAAG;oBAC1C,OAAO,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;oBACpH,UAAU,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAC9B,CAAA;YACH,CAAC;QACH,CAAC;QAED,mCAAmC;QACnC,2BAA2B;QAC3B,MAAM,aAAa,GAAG;YACpB,EAAE,MAAM,EAAE,IAAI,CAAC,gBAAgB,EAAE,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE;YACzE,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;SAC5C,CAAA;QAED,IAAI,iBAAiB,GAAiB,EAAE,CAAA;QAExC,KAAK,MAAM,OAAO,IAAI,aAAa,EAAE,CAAC;YACpC,qBAAqB;YACrB,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC;gBAAE,MAAK;YAEvC,KAAK,MAAM,GAAG,IAAI,iBAAiB,EAAE,CAAC;gBACpC,QAAQ;gBACR,IAAI,GAAG,CAAC,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,cAAc;oBAAE,SAAQ;gBAExD,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,GAAG,CAAA;gBAE1B,6BAA6B;gBAC7B,IAAI,UAAU,GAAG,KAAK,CAAA;gBACtB,IAAI,OAAO,GAAG,QAAQ,CAAA;gBACtB,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;oBAC7B,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,kBAAkB,CACpC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EACV,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAChB,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CACb,CAAA;oBACD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;wBAC/E,UAAU,GAAG,IAAI,CAAA;wBACjB,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;oBACnC,CAAC;gBACH,CAAC;gBACD,IAAI,CAAC,UAAU;oBAAE,SAAQ;gBAEzB,sBAAsB;gBACtB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;gBACzE,IAAI,MAAM,GAAG,KAAK;oBAAE,SAAQ;gBAC5B,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAA;gBAC1C,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAA;gBAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC,CAAA;gBAC3D,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,CAAA;gBAE3D,IAAI,KAAK,GAAG,IAAI,CAAC,cAAc;oBAAE,SAAQ;gBAEzC,kBAAkB;gBAClB,iBAAiB,CAAC,IAAI,CAAC;oBACrB,GAAG;oBACH,OAAO;oBACP,KAAK,EAAE,GAAG,CAAC,MAAM,GAAG,OAAO;oBAC3B,KAAK,EAAE,CAAC;oBACR,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE;iBAC/C,CAAC,CAAA;YACJ,CAAC;YAED,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACjC,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,KAAK,SAAS,iBAAiB,CAAC,MAAM,MAAM,CAAC,CAAA;YACnG,CAAC;QACH,CAAC;QAED,QAAQ;QACR,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjC,KAAK,MAAM,EAAE,IAAI,iBAAiB,EAAE,CAAC;gBACnC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,WAAW,EAAE,YAAY,CAAC,CAAA;gBAC9E,EAAE,CAAC,KAAK,GAAG,KAAK,CAAA;gBAChB,EAAE,CAAC,OAAO,GAAG,OAAO,CAAA;YACtB,CAAC;YACD,gBAAgB;YAChB,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,CAAA;YAE5E,MAAM,IAAI,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAA;YACjC,MAAM,SAAS,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAC1C,MAAM,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,CAAC,OAAO,CAAC,QAAQ,SAAS,CAAC,CAAC,OAAO,CAAC,QAAQ,UAAU,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAC1H,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YACb,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,CAAC,IAAI,UAAU,SAAS,EAAE,CAAC,CAAA;YAC9D,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,CAAC,IAAI,WAAW,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,IAAI,QAAQ,IAAI,CAAC,OAAO,CAAC,QAAQ,SAAS,IAAI,CAAC,OAAO,CAAC,QAAQ,UAAU,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;QACzL,CAAC;aAAM,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1C,iBAAiB,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAA,CAAC,YAAY;QAC9C,CAAC;QAED,IAAI,QAAQ,GAAG,QAAQ,CAAA;QACvB,IAAI,SAAS,GAAG,CAAC,CAAA;QAEjB,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAA;YACnC,OAAO,GAAG,MAAM,CAAC,GAAG,CAAA;YACpB,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAA;YACzB,SAAS,GAAG,MAAM,CAAC,KAAK,CAAA;QAC1B,CAAC;QAED,qBAAqB;QACrB,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACzC,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,CAAC,IAAI,WAAW,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;QAC5O,CAAC;QAED,sCAAsC;QACtC,0DAA0D;QAC1D,gDAAgD;QAChD,IAAI,OAAO,GAAQ,SAAS,CAAA;QAC5B,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;YAC7C,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;YAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC,CAAA;YAC1D,MAAM,OAAO,GAAG,KAAK,GAAG,SAAS,CAAA;YACjC,MAAM,OAAO,GAAG,KAAK,GAAG,SAAS,CAAA;YAEjC,oCAAoC;YACpC,MAAM,QAAQ,GAAa,EAAE,CAAA;YAC7B,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;gBAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;gBAC7C,MAAM,KAAK,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;gBAC7C,MAAM,IAAI,GAAG,CAAC,KAAK,GAAG,OAAO,GAAG,KAAK,GAAG,OAAO,CAAC,GAAG,SAAS,CAAA;gBAC5D,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACrB,CAAC;YACD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAA;YACrC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAA;YACrC,MAAM,QAAQ,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC,GAAG,SAAS,CAAA;YAChD,MAAM,OAAO,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;YACvC,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,OAAO,GAAG,KAAK,CAAA;YAClD,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,OAAO,GAAG,KAAK,CAAA;YAElD,MAAM,UAAU,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;YAChC,MAAM,UAAU,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;YAChC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,UAAU,CAAC,CAAA;YACnD,MAAM,SAAS,GAAG,kBAAkB,CAAC,cAAc,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;YACtF,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC,CAAA;YACnD,MAAM,OAAO,GAAG,OAAO,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,CAAA;YAE5C,OAAO,GAAG;gBACR,CAAC,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,UAAU,GAAG,SAAS,GAAG,CAAC,EAAE;gBAC9D,KAAK,EAAE,QAAQ;gBACf,IAAI,EAAE,OAAO;gBACb,MAAM,EAAE,SAAS;gBACjB,eAAe,EAAE,OAAO;aACzB,CAAA;YAED,+BAA+B;YAC/B,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAA;YAC9D,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;gBACpB,MAAM,EAAE,GAAG,OAAgD,CAAA;gBAC3D,IAAI,CAAC,EAAE,CAAC,UAAU;oBAAE,EAAE,CAAC,UAAU,GAAG,EAAE,CAAA;gBACtC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YAC7B,CAAC;QACH,CAAC;QAED,uBAAuB;QACvB,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC;gBACX,UAAU,EAAE,GAAG,CAAC,IAAI;gBACpB,cAAc,EAAE,GAAG,CAAC,QAAQ;gBAC5B,YAAY,EAAE,GAAG,CAAC,MAAM;gBACxB,WAAW,EAAE,OAAO;gBACpB,QAAQ,EAAE,QAAQ;gBAClB,eAAe,EAAE,SAAS;gBAC1B,UAAU,EAAE,OAAO;aACpB,CAAC,CAAA;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,oBAAoB,GAAG,CAAC,IAAI,YAAY,CAAC,CAAA;QACxD,CAAC;IACH,CAAC;IAED,mCAAmC;IACnC,qCAAqC;IACrC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,EAAE,GAAG,CAAC,CAAC,WAAW,CAAA;QACxB,8BAA8B;QAC9B,MAAM,EAAE,GAAG,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QACrC,IAAI,EAAE,KAAK,CAAC,CAAC;YAAE,SAAQ,CAAC,mBAAmB;QAC3C,MAAM,OAAO,GAAG,cAAc,CAAC,EAAE,CAAC,CAAA;QAClC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC;YAAE,SAAQ,CAAC,YAAY;QAC1D,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAA;QAC/D,SAAS;QACT,MAAM,SAAS,GAAc,EAAE,CAAA;QAC/B,MAAM,OAAO,GAAc,EAAE,CAAA;QAC7B,MAAM,OAAO,GAAc,EAAE,CAAA;QAC7B,MAAM,WAAW,GAAc,EAAE,CAAA;QACjC,MAAM,UAAU,GAAiB,EAAE,CAAA;QACnC,IAAI,OAAO,GAA2B,SAAS,CAAA;QAC/C,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM;gBAAE,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM;oBAAE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjE,IAAI,CAAC,CAAC,cAAc,EAAE,MAAM;gBAAE,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,cAAc;oBAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YAC/E,IAAI,CAAC,CAAC,eAAe,EAAE,MAAM;gBAAE,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,eAAe;oBAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjF,IAAI,CAAC,CAAC,WAAW,EAAE,MAAM;gBAAE,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW;oBAAE,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YAC7E,IAAI,CAAC,CAAC,UAAU,EAAE,MAAM;gBAAE,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,UAAU;oBAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YAC1E,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,OAAO;gBAAE,OAAO,GAAG,CAAC,CAAC,OAAO,CAAA;QAChD,CAAC;QACD,IAAI,SAAS,CAAC,MAAM;YAAE,EAAE,CAAC,MAAM,GAAG,SAAS,CAAA;QAC3C,IAAI,OAAO,CAAC,MAAM;YAAE,EAAE,CAAC,cAAc,GAAG,OAAO,CAAA;QAC/C,IAAI,OAAO,CAAC,MAAM;YAAE,EAAE,CAAC,eAAe,GAAG,OAAO,CAAA;QAChD,IAAI,WAAW,CAAC,MAAM;YAAE,EAAE,CAAC,WAAW,GAAG,WAAW,CAAA;QACpD,IAAI,UAAU,CAAC,MAAM;YAAE,EAAE,CAAC,UAAU,GAAG,UAAU,CAAA;QACjD,IAAI,OAAO;YAAE,EAAE,CAAC,OAAO,GAAG,OAAO,CAAA;QACjC,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,OAAO,CAAC,GAAG,CACT,oBAAoB,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM;gBACnF,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG;gBACrD,eAAe,GAAG,OAAO,CAAC,MAAM,GAAG,WAAW;gBAC9C,cAAc,GAAG,UAAU,CAAC,MAAM,GAAG,QAAQ,CAC9C,CAAA;QACH,CAAC;IACH,CAAC;IAED,kDAAkD;IAClD,6CAA6C;IAC7C,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAc,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IAChG,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,0CAA0C,GAAG,KAAK,CAAC,MAAM,CAAC,CAAA;QACtE,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CACT,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM;gBACrF,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG;gBACpF,aAAa,GAAG,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAC7E,CAAA;YACD,MAAM,EAAE,GAAG,CAAC,CAAC,UAAW,CAAA;YACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACrC,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,CAAA;gBACpB,OAAO,CAAC,GAAG,CACT,iBAAiB,GAAG,CAAC,GAAG,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;oBACrF,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;oBAC7E,oBAAoB,GAAG,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,GAAG,MAAM,CAAC,IAAI,CACnF,CAAA;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { WallSegment, WindowObject, FindWallOptions } from './findWindowWall';
2
+ export { findWindowWalls, mergeCollinearSegments, computeLocalFloorZ, } from './findWindowWall';
3
+ export type { Point3D, DrawWindow, WallSegment, WindowObject, FindWallOptions, } from './findWindowWall';
4
+ import type { Point3D, DrawWindow } from './findWindowWall';
5
+ export interface WallWindowMatch {
6
+ windowName: string;
7
+ windowCategory: string;
8
+ windowCenter: Point3D;
9
+ wallSegment: WallSegment;
10
+ distance: number;
11
+ wallLengthRatio: number;
12
+ drawWindow?: DrawWindow;
13
+ }
14
+ /**
15
+ * 处理主函数:墙线段数组 + 物体数组 → 匹配窗户 → 输出带 drawWindow 的墙线段
16
+ * 纯算法,不依赖 Node API,可在浏览器中调用
17
+ */
18
+ export declare function processData(wallSegments: WallSegment[], windowObjects: WindowObject[], options?: FindWallOptions & {
19
+ printOnly?: boolean;
20
+ }): {
21
+ segments: WallSegment[];
22
+ matches: WallWindowMatch[];
23
+ sourceMap: number[][];
24
+ };
25
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,WAAW,EACX,YAAY,EACZ,eAAe,EAEhB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,kBAAkB,CAAA;AAEzB,YAAY,EACV,OAAO,EACP,UAAU,EACV,WAAW,EACX,YAAY,EACZ,eAAe,GAChB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAG3D,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc,EAAE,MAAM,CAAA;IACtB,YAAY,EAAE,OAAO,CAAA;IACrB,WAAW,EAAE,WAAW,CAAA;IACxB,QAAQ,EAAE,MAAM,CAAA;IAChB,eAAe,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,UAAU,CAAA;CACxB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,YAAY,EAAE,WAAW,EAAE,EAC3B,aAAa,EAAE,YAAY,EAAE,EAC7B,OAAO,CAAC,EAAE,eAAe,GAAG;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAClD;IAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;IAAC,OAAO,EAAE,eAAe,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,EAAE,CAAA;CAAE,CA4BhF"}
package/dist/index.js ADDED
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ // wall-window-matcher 主入口
3
+ // 说明:此文件只包含纯算法函数(无 Node fs/path 依赖),可被浏览器/Vite 直接 import
4
+ // 若需要命令行工具,使用 cli.ts:npx tsx src/cli.ts <walls.json> <objects.json> [output.json]
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.computeLocalFloorZ = exports.mergeCollinearSegments = exports.findWindowWalls = void 0;
7
+ exports.processData = processData;
8
+ const findWindowWall_1 = require("./findWindowWall");
9
+ // 重新导出所有前端需要的函数和类型
10
+ var findWindowWall_2 = require("./findWindowWall");
11
+ Object.defineProperty(exports, "findWindowWalls", { enumerable: true, get: function () { return findWindowWall_2.findWindowWalls; } });
12
+ Object.defineProperty(exports, "mergeCollinearSegments", { enumerable: true, get: function () { return findWindowWall_2.mergeCollinearSegments; } });
13
+ Object.defineProperty(exports, "computeLocalFloorZ", { enumerable: true, get: function () { return findWindowWall_2.computeLocalFloorZ; } });
14
+ /**
15
+ * 处理主函数:墙线段数组 + 物体数组 → 匹配窗户 → 输出带 drawWindow 的墙线段
16
+ * 纯算法,不依赖 Node API,可在浏览器中调用
17
+ */
18
+ function processData(wallSegments, windowObjects, options) {
19
+ const opts = {
20
+ printOnly: false,
21
+ ...options,
22
+ };
23
+ const matches = (0, findWindowWall_1.findWindowWalls)(windowObjects, wallSegments, opts);
24
+ // 合并后的墙线段(用于输出)
25
+ const { segments: mergedSegments, sourceMap } = (0, findWindowWall_1.mergeCollinearSegments)(wallSegments);
26
+ // 将 drawWindow 数据合并到对应的墙线段中
27
+ for (const match of matches) {
28
+ if (match.drawWindow) {
29
+ const seg = mergedSegments.find((s) => Math.abs(s.start.x - match.wallSegment.start.x) < 0.01 &&
30
+ Math.abs(s.start.y - match.wallSegment.start.y) < 0.01 &&
31
+ Math.abs(s.end.x - match.wallSegment.end.x) < 0.01 &&
32
+ Math.abs(s.end.y - match.wallSegment.end.y) < 0.01);
33
+ if (seg) {
34
+ if (!seg.drawWindow)
35
+ seg.drawWindow = [];
36
+ seg.drawWindow.push(match.drawWindow);
37
+ }
38
+ }
39
+ }
40
+ return { segments: mergedSegments, matches, sourceMap };
41
+ }
42
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,0BAA0B;AAC1B,yDAAyD;AACzD,kFAAkF;;;AA4ClF,kCAgCC;AA1ED,qDAOyB;AAEzB,mBAAmB;AACnB,mDAIyB;AAHvB,iHAAA,eAAe,OAAA;AACf,wHAAA,sBAAsB,OAAA;AACtB,oHAAA,kBAAkB,OAAA;AAyBpB;;;GAGG;AACH,SAAgB,WAAW,CACzB,YAA2B,EAC3B,aAA6B,EAC7B,OAAmD;IAEnD,MAAM,IAAI,GAA6C;QACrD,SAAS,EAAE,KAAK;QAChB,GAAG,OAAO;KACX,CAAA;IAED,MAAM,OAAO,GAAG,IAAA,gCAAe,EAAC,aAAa,EAAE,YAAY,EAAE,IAAI,CAAC,CAAA;IAElE,gBAAgB;IAChB,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,SAAS,EAAE,GAAG,IAAA,uCAAsB,EAAC,YAAY,CAAC,CAAA;IAEpF,4BAA4B;IAC5B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;YACrB,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,CAAc,EAAE,EAAE,CACjD,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI;gBACtD,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI;gBACtD,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI;gBAClD,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CACnD,CAAA;YACD,IAAI,GAAG,EAAE,CAAC;gBACR,IAAI,CAAC,GAAG,CAAC,UAAU;oBAAE,GAAG,CAAC,UAAU,GAAG,EAAE,CAAA;gBACxC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;YACvC,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE,CAAA;AACzD,CAAC"}
package/package.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "wall-window-matcher",
3
+ "version": "1.1.0",
4
+ "description": "建筑点云 —— 墙线段共线合并 + 窗户匹配 + drawWindow 属性注入(浏览器/Node 通用)",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "bin": {
8
+ "wall-window-matcher": "dist/cli.js"
9
+ },
10
+ "files": ["dist"],
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "prepublishOnly": "npm run build"
14
+ },
15
+ "keywords": ["building", "point-cloud", "window", "wall", "matching"],
16
+ "license": "MIT"
17
+ }