@caoguo/maplibre-pipeline 0.0.5 → 0.0.7
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 +46 -18
- package/dist/burst/index.cjs.map +1 -1
- package/dist/burst/index.js +2 -2
- package/dist/{chunk-HCT6NSNS.js → chunk-2O4IXAXO.js} +3 -3
- package/dist/{chunk-HCT6NSNS.js.map → chunk-2O4IXAXO.js.map} +1 -1
- package/dist/{chunk-3656CGXE.js → chunk-33TITD2I.js} +31 -3
- package/dist/chunk-33TITD2I.js.map +1 -0
- package/dist/{chunk-QVY4WJLM.js → chunk-4HP7Q7OL.js} +6 -3
- package/dist/chunk-4HP7Q7OL.js.map +1 -0
- package/dist/{chunk-YBLESEN4.js → chunk-7LPD52KL.js} +34 -5
- package/dist/chunk-7LPD52KL.js.map +1 -0
- package/dist/{chunk-BWQKY35F.js → chunk-ASITLG37.js} +3 -3
- package/dist/{chunk-BWQKY35F.js.map → chunk-ASITLG37.js.map} +1 -1
- package/dist/{chunk-GCDA7KJM.js → chunk-XCP7XVNO.js} +5 -8
- package/dist/chunk-XCP7XVNO.js.map +1 -0
- package/dist/{chunk-YS2ICFVK.js → chunk-YB2PMLA6.js} +3 -3
- package/dist/{chunk-YS2ICFVK.js.map → chunk-YB2PMLA6.js.map} +1 -1
- package/dist/graph/index.cjs +3 -6
- package/dist/graph/index.cjs.map +1 -1
- package/dist/graph/index.d.cts +4 -0
- package/dist/graph/index.d.ts +4 -0
- package/dist/graph/index.js +1 -1
- package/dist/health/index.cjs +30 -0
- package/dist/health/index.cjs.map +1 -1
- package/dist/health/index.d.cts +29 -1
- package/dist/health/index.d.ts +29 -1
- package/dist/health/index.js +1 -1
- package/dist/index.cjs +68 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +7 -7
- package/dist/nlpg/index.cjs +32 -3
- package/dist/nlpg/index.cjs.map +1 -1
- package/dist/nlpg/index.d.cts +20 -6
- package/dist/nlpg/index.d.ts +20 -6
- package/dist/nlpg/index.js +1 -1
- package/dist/style/index.cjs +4 -0
- package/dist/style/index.cjs.map +1 -1
- package/dist/style/index.d.cts +3 -1
- package/dist/style/index.d.ts +3 -1
- package/dist/style/index.js +2 -2
- package/dist/topology/index.cjs +2 -2
- package/dist/topology/index.cjs.map +1 -1
- package/dist/topology/index.js +2 -2
- package/package.json +3 -3
- package/dist/chunk-3656CGXE.js.map +0 -1
- package/dist/chunk-GCDA7KJM.js.map +0 -1
- package/dist/chunk-QVY4WJLM.js.map +0 -1
- package/dist/chunk-YBLESEN4.js.map +0 -1
package/README.md
CHANGED
|
@@ -32,29 +32,29 @@ Peer:`maplibre-gl@^4.7.1`。
|
|
|
32
32
|
### 爆管推演
|
|
33
33
|
|
|
34
34
|
```ts
|
|
35
|
-
import { BurstSimulator
|
|
35
|
+
import { BurstSimulator } from '@caoguo/maplibre-pipeline/burst';
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
});
|
|
42
|
-
const result = sim.simulate();
|
|
37
|
+
// 构造需要地图实例与拓扑数据集
|
|
38
|
+
const sim = new BurstSimulator({ map: mapInstance, dataset });
|
|
39
|
+
// 对指定爆管管段推演:返回影响节点、应关闭阀门、受影响用户
|
|
40
|
+
const result = sim.simulate('P-001');
|
|
43
41
|
console.log('影响节点数', result.affectedNodes.length);
|
|
44
42
|
console.log('应关阀门', result.valvesToClose);
|
|
45
43
|
```
|
|
46
44
|
|
|
47
|
-
###
|
|
45
|
+
### 泄漏扩散(高斯烟羽 + 洪水淹没)
|
|
48
46
|
|
|
49
47
|
```ts
|
|
50
|
-
import { LeakagePlume
|
|
48
|
+
import { LeakagePlume } from '@caoguo/maplibre-pipeline/leakage';
|
|
51
49
|
|
|
52
50
|
const plume = new LeakagePlume({
|
|
51
|
+
map: mapInstance,
|
|
53
52
|
source: { lng: 114.3, lat: 30.6, heightMeters: 2 },
|
|
54
53
|
wind: { speedMps: 3, directionDeg: 45 },
|
|
55
|
-
stabilityClass: 'D', // Pasquill-Gifford
|
|
54
|
+
stabilityClass: 'D', // Pasquill-Gifford 稳定度等级
|
|
56
55
|
});
|
|
57
|
-
|
|
56
|
+
// 推演 1 小时后等浓度线(高斯烟羽)或洪水淹没范围
|
|
57
|
+
const contour = plume.simulate({ seconds: 3600, mode: 'gaussian' });
|
|
58
58
|
```
|
|
59
59
|
|
|
60
60
|
### 管线健康评分
|
|
@@ -63,8 +63,36 @@ const contour = plume.simulate(3600); // 1 小时后的等浓度线
|
|
|
63
63
|
import { PipelineHealth } from '@caoguo/maplibre-pipeline/health';
|
|
64
64
|
|
|
65
65
|
const health = new PipelineHealth({ dataset });
|
|
66
|
-
const
|
|
67
|
-
console.log(score.total, score.
|
|
66
|
+
const report = health.evaluate('P-001'); // 单管多维加权评分
|
|
67
|
+
console.log('综合得分', report.score.total, '等级', report.score.level);
|
|
68
|
+
// 维度明细
|
|
69
|
+
for (const d of report.factors) console.log(d.dimension, d.weight, d.value);
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 自然语言查询 + 爆管联动
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
import { PipelineNlp } from '@caoguo/maplibre-pipeline/nlpg';
|
|
76
|
+
import { BurstSimulator } from '@caoguo/maplibre-pipeline/burst';
|
|
77
|
+
|
|
78
|
+
const nlp = new PipelineNlp({
|
|
79
|
+
burstSimulator: new BurstSimulator({ map: mapInstance, dataset }),
|
|
80
|
+
dataset,
|
|
81
|
+
});
|
|
82
|
+
// 识别为爆管意图时自动联动推演并缓存结果
|
|
83
|
+
const res = nlp.query('朝阳门外大街燃气爆管');
|
|
84
|
+
console.log('意图', res.intent); // 'burst'
|
|
85
|
+
console.log('推演结果', nlp.getLastBurst()); // { affectedNodes, valvesToClose, affectedUsers }
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 上游隔离阀查找(纯函数)
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
import { findUpstreamNode, buildAdjacency } from '@caoguo/maplibre-pipeline/graph';
|
|
92
|
+
|
|
93
|
+
const adj = buildAdjacency(dataset);
|
|
94
|
+
const valve = findUpstreamNode(adj, 'P-001', dataset, (n) => n.kind === 'valve');
|
|
95
|
+
console.log('应关闭的上游阀门', valve?.id);
|
|
68
96
|
```
|
|
69
97
|
|
|
70
98
|
### 拓扑编辑器(与 @caoguo/maplibre 配合)
|
|
@@ -85,7 +113,7 @@ topo.mount();
|
|
|
85
113
|
```ts
|
|
86
114
|
import { bfs } from '@caoguo/maplibre-pipeline/graph';
|
|
87
115
|
import { healthLevel } from '@caoguo/maplibre-pipeline/style';
|
|
88
|
-
import { pipelineNlp } from '@caoguo/maplibre-pipeline/nlpg';
|
|
116
|
+
import { PipelineNlp, pipelineNlp } from '@caoguo/maplibre-pipeline/nlpg';
|
|
89
117
|
```
|
|
90
118
|
|
|
91
119
|
可用子路径:`./graph`、`./topology`、`./burst`、`./leakage`、`./health`、`./nlpg`、`./style`、`./types`。
|
|
@@ -93,14 +121,14 @@ import { pipelineNlp } from '@caoguo/maplibre-pipeline/nlpg';
|
|
|
93
121
|
## 设计原则
|
|
94
122
|
|
|
95
123
|
1. **算法纯函数 + 渲染薄壳**:所有算法可在 Node 环境单测。
|
|
96
|
-
2.
|
|
97
|
-
3.
|
|
98
|
-
4.
|
|
124
|
+
2. **可插拔**:每个组件独立可用,也可组合(如 Topology + Burst + Health)。
|
|
125
|
+
3. **离线友好**:所有计算在前端完成,无需后端依赖(Phase 1 MVP 离线优先)。
|
|
126
|
+
4. **可解释**:评分/推演结果结构包含各维度明细,便于逐维追溯到依据。
|
|
99
127
|
|
|
100
128
|
## 浏览器 / 环境要求
|
|
101
129
|
|
|
102
130
|
- 现代浏览器(Chrome 90+)
|
|
103
|
-
- 核心算法模块可在 Node.js 测试(已含
|
|
131
|
+
- 核心算法模块可在 Node.js 测试(已含 71 个 vitest 用例)
|
|
104
132
|
|
|
105
133
|
## 许可
|
|
106
134
|
|
package/dist/burst/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/graph/adjacency.ts","../../src/graph/bfs.ts","../../src/graph/shortestPath.ts","../../src/graph/connectivity.ts","../../src/burst/burstCore.ts","../../src/burst/valvePlanner.ts","../../src/burst/impactArea.ts","../../src/burst/burstClass.ts"],"names":["cur"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * 图邻接表构建(管线拓扑 → 双向邻接表)\n *\n * 输入:管网拓扑数据集(节点 + 管段)\n * 输出:邻接表 Map<nodeId, Edge[]>\n *\n * Phase 1 图遍历的入口:把物理拓扑转换为图论可用的数据结构。\n */\n\nimport type {\n PipelineNode,\n PipelinePipe,\n PipelineTopologyDataset,\n} from '../types';\n\n/**\n * 邻接表中的\"边\"\n * - 物理上一条 pipe 是两个 node 之间的连接\n * - 邻接表中记录:pipeId、邻居节点 id、长度等\n */\nexport interface AdjEdge {\n pipeId: string;\n /** 邻居节点 id(沿此边走一步到达) */\n to: string;\n /** 长度(m),无则 0 */\n length: number;\n /** 阻力/权重(用于复杂路径优选,可选) */\n weight?: number;\n}\n\n/** 邻接表:Map<nodeId, AdjEdge[]> */\nexport type AdjacencyList = Map<string, AdjEdge[]>;\n\n/**\n * 从 PipelineTopologyDataset 构建邻接表\n */\nexport function buildAdjacency(dataset: PipelineTopologyDataset): AdjacencyList {\n const adj: AdjacencyList = new Map();\n\n // 初始化所有节点(防止孤立点不出现)\n for (const node of dataset.nodes) {\n if (!adj.has(node.id)) adj.set(node.id, []);\n }\n\n for (const pipe of dataset.pipes) {\n const len = pipe.length ?? pipeLengthFromGeometry(pipe, dataset.nodes) ?? 0;\n\n const fromList = adj.get(pipe.fromNode) ?? [];\n fromList.push({\n pipeId: pipe.id,\n to: pipe.toNode,\n length: len,\n });\n adj.set(pipe.fromNode, fromList);\n\n const toList = adj.get(pipe.toNode) ?? [];\n toList.push({\n pipeId: pipe.id,\n to: pipe.fromNode,\n length: len,\n });\n adj.set(pipe.toNode, toList);\n }\n\n return adj;\n}\n\n/**\n * 计算单条 pipe 长度(haversine)\n * 若 pipe 提供 geometry 则累计几何点距离,否则按 from-to 直线长度。\n */\nexport function pipeLengthFromGeometry(\n pipe: PipelinePipe,\n nodes: PipelineNode[]\n): number {\n if (pipe.length && pipe.length > 0) return pipe.length;\n if (pipe.geometry && pipe.geometry.length >= 2) {\n let total = 0;\n for (let i = 1; i < pipe.geometry.length; i++) {\n total += haversine(\n pipe.geometry[i - 1][0],\n pipe.geometry[i - 1][1],\n pipe.geometry[i][0],\n pipe.geometry[i][1]\n );\n }\n return total;\n }\n const from = nodes.find((n) => n.id === pipe.fromNode);\n const to = nodes.find((n) => n.id === pipe.toNode);\n if (!from || !to) return 0;\n return haversine(from.lng, from.lat, to.lng, to.lat);\n}\n\n/** Haversine 距离(m) */\nexport function haversine(\n lng1: number,\n lat1: number,\n lng2: number,\n lat2: number\n): number {\n const R = 6_371_000;\n const toRad = (d: number) => (d * Math.PI) / 180;\n const dLat = toRad(lat2 - lat1);\n const dLng = toRad(lng2 - lng1);\n const a =\n Math.sin(dLat / 2) ** 2 +\n Math.cos(toRad(lat1)) *\n Math.cos(toRad(lat2)) *\n Math.sin(dLng / 2) ** 2;\n return 2 * R * Math.asin(Math.sqrt(a));\n}\n\n/** 从邻接表拿指定节点的邻居 id 列表(去重) */\nexport function neighborIds(adj: AdjacencyList, nodeId: string): string[] {\n const list = adj.get(nodeId) ?? [];\n const seen = new Set<string>();\n const out: string[] = [];\n for (const e of list) {\n if (!seen.has(e.to)) {\n seen.add(e.to);\n out.push(e.to);\n }\n }\n return out;\n}\n\n/** 取出指定节点的所有边 */\nexport function edgesOf(adj: AdjacencyList, nodeId: string): AdjEdge[] {\n return adj.get(nodeId) ?? [];\n}\n","/**\n * BFS(广度优先遍历)\n *\n * 用途:\n * - 爆管推演:下游影响范围(沿拓扑扩散)\n * - 连通性查询:在指定层级内查找可达节点\n *\n * 实现要点:\n * - 支持 visited / parents 记录\n * - 支持 maxDepth 限制(避免极大连通分量过长)\n * - 支持 predicate 过滤可继续遍历的邻居\n * - 可返回\"沿途经过的管段\"列表(用于前端高亮)\n */\n\nimport type { AdjacencyList, AdjEdge } from './adjacency';\n\nexport interface BfsResult {\n /** 访问过的节点(不重复) */\n visited: string[];\n /** 父节点表:node -> 上一步到达的 node(首节点为自身) */\n parents: Map<string, string | null>;\n /** 起点 节点 */\n start: string;\n /** 终点节点(搜到即停,返回时 visited 是到终点为止的节点) */\n end?: string;\n}\n\nexport interface BfsOptions {\n /** 最大深度(边数),默认无限制 */\n maxDepth?: number;\n /** 是否指定终点(BFS 找到则停止) */\n until?: (node: string) => boolean;\n /** 在扩展邻居前过滤:false 则该方向不继续遍历 */\n allowEdge?: (edge: AdjEdge, from: string, to: string) => boolean;\n /** 起点本身的过滤器(如只走下游/上游) */\n allowStart?: (node: string) => boolean;\n}\n\n/**\n * 标准 BFS,可指定\"任意邻居是否可达\"\n *\n * 用法:\n * const r = bfs(adj, 'node-A');\n * bfs(adj, 'start', { until: (n) => n === 'target' }); // 找终点\n * bfs(adj, 'start', { allowEdge: (_, __, to) => to !== 'forbidden' });\n */\nexport function bfs(\n adj: AdjacencyList,\n start: string,\n opts: BfsOptions = {}\n): BfsResult {\n const visited: string[] = [];\n const parents = new Map<string, string | null>();\n const visitedSet = new Set<string>();\n\n if (!adj.has(start)) {\n parents.set(start, null);\n return { visited, parents, start };\n }\n\n if (opts.allowStart && !opts.allowStart(start)) {\n return { visited: [], parents, start };\n }\n\n const queue: Array<{ id: string; depth: number }> = [{ id: start, depth: 0 }];\n parents.set(start, null);\n visitedSet.add(start);\n visited.push(start);\n\n let foundEnd: string | undefined;\n while (queue.length > 0) {\n const { id, depth } = queue.shift()!;\n\n if (opts.until && opts.until(id)) {\n foundEnd = id;\n break;\n }\n\n // maxDepth 语义:最多走 N 条边,到达节点的最短路径长度为 N\n // 当前节点 depth=d = 经过 d 条边到达,扩展邻居须 depth+1 <= maxDepth\n if (opts.maxDepth !== undefined && depth >= opts.maxDepth) continue;\n\n const edges = adj.get(id) ?? [];\n for (const e of edges) {\n if (opts.allowEdge && !opts.allowEdge(e, id, e.to)) continue;\n if (visitedSet.has(e.to)) continue;\n visitedSet.add(e.to);\n parents.set(e.to, id);\n visited.push(e.to);\n queue.push({ id: e.to, depth: depth + 1 });\n }\n }\n\n return { visited, parents, start, end: foundEnd };\n}\n\n/**\n * 多源 BFS(同时从多个起点扩散)\n *\n * 用法:爆管分析的下游影响可从多点同时推演(如多个隔离阀门的下游剩余服务区)\n */\nexport function multiSourceBfs(\n adj: AdjacencyList,\n starts: string[],\n opts: BfsOptions = {}\n): BfsResult & { sourceMap: Map<string, string> } {\n const visited: string[] = [];\n const parents = new Map<string, string | null>();\n const sourceMap = new Map<string, string>();\n const visitedSet = new Set<string>();\n\n const queue: Array<{ id: string; depth: number }> = [];\n\n for (const s of starts) {\n if (!adj.has(s)) continue;\n if (opts.allowStart && !opts.allowStart(s)) continue;\n if (!visitedSet.has(s)) {\n visitedSet.add(s);\n parents.set(s, null);\n sourceMap.set(s, s);\n visited.push(s);\n queue.push({ id: s, depth: 0 });\n }\n }\n\n while (queue.length > 0) {\n const { id, depth } = queue.shift()!;\n // 同单源 BFS:depth=d 时扩展邻居;maxDepth=N 表示最多 N 条边\n if (opts.maxDepth !== undefined && depth >= opts.maxDepth) continue;\n\n const edges = adj.get(id) ?? [];\n for (const e of edges) {\n if (opts.allowEdge && !opts.allowEdge(e, id, e.to)) continue;\n if (visitedSet.has(e.to)) continue;\n visitedSet.add(e.to);\n parents.set(e.to, id);\n sourceMap.set(e.to, sourceMap.get(id)!);\n visited.push(e.to);\n queue.push({ id: e.to, depth: depth + 1 });\n }\n }\n\n return { visited, parents, start: starts[0] ?? '', sourceMap };\n}\n\n/**\n * 反向 BFS(沿父指针回溯)\n *\n * 给定终点 + parents Map,可还原 BFS 路径(用于\"找到的最短路径\")。\n */\nexport function reconstructPath(\n parents: Map<string, string | null>,\n end: string\n): string[] {\n const path: string[] = [];\n let cur: string | null = end;\n while (cur) {\n path.unshift(cur);\n const p = parents.get(cur);\n cur = p ?? null;\n if (cur === null && p === null) {\n // 起点到达\n if (parents.get(end) === null && path.length === 1) break;\n break;\n }\n }\n if (path[0] !== end) {\n // already include end correctly\n }\n return path;\n}\n","/**\n * 最短路径(Dijkstra)\n *\n * 用途:\n * - 上游距离最近的阀门定位\n * - 备选供气/供水路径(按管径/压力选优)\n */\n\nimport type { AdjacencyList, AdjEdge } from './adjacency';\n\nexport interface ShortestPathResult {\n distance: number;\n path: string[];\n found: boolean;\n}\n\nexport interface ShortestPathOptions {\n /** 边权重函数:默认 1 */\n weight?: (edge: AdjEdge) => number;\n /** 提前终止:找到满足条件的节点立即返回 */\n until?: (node: string, dist: number) => boolean;\n}\n\n/**\n * Dijkstra 最短路径\n *\n * 注意:当存在负权边时不可用;管网场景边权重非负,管长/管径均适用。\n */\nexport function dijkstra(\n adj: AdjacencyList,\n start: string,\n end: string,\n opts: ShortestPathOptions = {}\n): ShortestPathResult {\n if (!adj.has(start) || !adj.has(end)) {\n return { distance: Infinity, path: [], found: false };\n }\n\n const weight = opts.weight ?? ((e: AdjEdge) => e.length || 1);\n\n const dist = new Map<string, number>();\n const parents = new Map<string, string | null>();\n const visited = new Set<string>();\n const pq: Array<{ id: string; d: number }> = [{ id: start, d: 0 }];\n\n for (const n of adj.keys()) {\n dist.set(n, Infinity);\n parents.set(n, null);\n }\n dist.set(start, 0);\n\n while (pq.length > 0) {\n // 简化:线性查找最小值(小图足够;大规模可换二叉堆)\n pq.sort((a, b) => a.d - b.d);\n const cur = pq.shift()!;\n if (visited.has(cur.id)) continue;\n visited.add(cur.id);\n if (cur.id === end) break;\n\n const edges = adj.get(cur.id) ?? [];\n for (const e of edges) {\n if (visited.has(e.to)) continue;\n const w = weight(e);\n const alt = (dist.get(cur.id) ?? Infinity) + w;\n if (alt < (dist.get(e.to) ?? Infinity)) {\n dist.set(e.to, alt);\n parents.set(e.to, cur.id);\n pq.push({ id: e.to, d: alt });\n }\n }\n\n if (opts.until && opts.until(cur.id, cur.d)) break;\n }\n\n if ((dist.get(end) ?? Infinity) === Infinity) {\n return { distance: Infinity, path: [], found: false };\n }\n\n // 回溯路径\n const path: string[] = [];\n let cur: string | null = end;\n while (cur) {\n path.unshift(cur);\n const p = parents.get(cur);\n if (p === undefined) break;\n cur = p;\n }\n\n return { distance: dist.get(end) ?? 0, path, found: true };\n}\n","/**\n * 连通性分析\n *\n * 用途:\n * - P-4 连通性高亮:选中管线后高亮上下游连通路径\n * - 健康评估的影响范围计算\n * - 用户问\"阀门X关闭后影响哪些小区?\"\n */\n\nimport type { AdjacencyList, AdjEdge } from './adjacency';\nimport { bfs } from './bfs';\nimport type { PipelineNode, PipelineTopologyDataset, NodeKind } from '../types';\n\n/**\n * 连通分量(连通子图)\n */\nexport interface ConnectedComponent {\n /** 节点集合 */\n nodes: string[];\n /** 节点数 */\n size: number;\n /** 是否包含 source 类型节点(影响气源/水源判定) */\n hasSource: boolean;\n}\n\n/**\n * 求所有连通分量\n */\nexport function findConnectedComponents(\n adj: AdjacencyList,\n nodes: PipelineNode[]\n): ConnectedComponent[] {\n const visited = new Set<string>();\n const components: ConnectedComponent[] = [];\n\n const kindById = new Map<string, NodeKind>();\n for (const n of nodes) kindById.set(n.id, n.kind);\n\n for (const nodeId of adj.keys()) {\n if (visited.has(nodeId)) continue;\n const r = bfs(adj, nodeId);\n let hasSource = false;\n for (const id of r.visited) {\n visited.add(id);\n if (kindById.get(id) === 'source') hasSource = true;\n }\n components.push({\n nodes: r.visited,\n size: r.visited.length,\n hasSource,\n });\n }\n\n return components;\n}\n\n/**\n * 找到两个节点之间的所有路径(k 短路)\n *\n * 用途:阀门隔离方案中\"备选路径\"分析\n * NOTE:DFS+Yen's 算法简化版,路径数 < 10 适用。\n */\nexport function findPaths(\n adj: AdjacencyList,\n start: string,\n end: string,\n opts: { maxPaths?: number; maxDepth?: number } = {}\n): string[][] {\n const maxPaths = opts.maxPaths ?? 3;\n const maxDepth = opts.maxDepth ?? 20;\n\n const all: string[][] = [];\n const path: string[] = [];\n const onPath = new Set<string>();\n\n const dfsLocal = (cur: string) => {\n if (all.length >= maxPaths) return;\n if (cur === end) {\n all.push([...path]);\n return;\n }\n if (path.length >= maxDepth) return;\n onPath.add(cur);\n path.push(cur);\n const edges = adj.get(cur) ?? [];\n for (const e of edges) {\n if (onPath.has(e.to)) continue;\n dfsLocal(e.to);\n if (all.length >= maxPaths) return;\n }\n path.pop();\n onPath.delete(cur);\n };\n\n dfsLocal(start);\n return all;\n}\n\n/**\n * 沿拓扑向上游找到最近的指定类型节点(默认阀门)\n *\n * 用途:爆管推演自动定位隔离点(PRD §4.2.4 step 1)\n */\nexport function findUpstreamNode(\n adj: AdjacencyList,\n startPipeId: string,\n dataset: PipelineTopologyDataset,\n predicate: (n: PipelineNode) => boolean\n): PipelineNode | null {\n const pipe = dataset.pipes.find((p) => p.id === startPipeId);\n if (!pipe) return null;\n\n const nodeById = new Map(dataset.nodes.map((n) => [n.id, n]));\n\n // 起始:pipe 任意一端的\"非故障方向\" → 选择 fromNode 作为查找起点\n const startId = pipe.fromNode;\n const startNode = nodeById.get(startId);\n if (!startNode) return null;\n\n // 反向游走:只允许沿\"反向\"(即 from 是 to,to 是 from)前进\n const allowEdge = (e: AdjEdge, _from: string, to: string) => {\n // 边界:pipe 同时含 startId 端则允许从 startId 反向走\n const targetPipe = dataset.pipes.find((p) => p.id === e.pipeId);\n if (!targetPipe) return false;\n // 始终允许走(无向图)\n return true;\n };\n\n // BFS 到上层直到命中 predicate\n const r = bfs(adj, startId, {\n allowEdge,\n until: (n) => {\n const node = nodeById.get(n);\n return node ? predicate(node) : false;\n },\n maxDepth: 50,\n });\n\n if (!r.end) return null;\n return nodeById.get(r.end) ?? null;\n}\n\n/**\n * 高亮连通路径(从起点 BFS,把沿途所有 pipe 收集起来)\n *\n * 用途:选中管段/节点 → 高亮上下游\n */\nexport function highlightConnectivity(\n adj: AdjacencyList,\n start: string\n): { nodeIds: Set<string>; edgeIds: Set<string> } {\n const r = bfs(adj, start, { maxDepth: 64 });\n const nodeIds = new Set(r.visited);\n const edgeIds = new Set<string>();\n\n for (const n of r.visited) {\n const edges = adj.get(n) ?? [];\n for (const e of edges) {\n // 只高亮两端都已访问的边\n if (nodeIds.has(e.to)) edgeIds.add(e.pipeId);\n }\n }\n\n return { nodeIds, edgeIds };\n}\n","/**\n * BurstSimulator 核心算法(纯函数)\n *\n * 模拟\"故障管段\"后:\n * 1. 找所有隔离候选阀门(沿故障 pipe 任意一端 BFS,候选上、下游最近阀门)\n * 2. 至少保留:上游最近阀门 + 下游最近阀门,确保\"故障段完全与气源/水源分离\"\n * 3. 下游 BFS(同时绕过被关闭阀门)找受影响节点\n * 4. 关联受影响用户(居民/商业/工业)\n * 5. 重要用户识别(医院/学校/工厂)\n * 6. 备选供气/供水路径(Dijkstra)\n *\n * 全部为纯函数,接收数据集返回结果,可在 Node/浏览器两侧运行。\n */\n\nimport type {\n PipelineTopologyDataset,\n PipelineNode,\n PipelinePipe,\n PipelineUser,\n UserKind,\n} from '../types';\nimport {\n buildAdjacency,\n type AdjacencyList,\n haversine,\n} from '../graph/adjacency';\nimport { bfs } from '../graph/bfs';\nimport { dijkstra } from '../graph/shortestPath';\nimport { findPaths } from '../graph/connectivity';\n\n/** 阀门隔离方案 */\nexport interface ValvePlan {\n /** 需关闭的阀门(隔离故障段) */\n closeValves: PipelineNode[];\n /** 需打开的阀门(泄压/排水) */\n openValves: PipelineNode[];\n /** 备选供气/供水路径(多源时才有) */\n alternativePaths: string[][];\n /** 预计停气/停水时间字符串(如 \"2h\"、\"45min\") */\n estimatedShutdownTime: string;\n /** 隔离方案的可读摘要 */\n summary: string;\n}\n\n/** 影响区域(受影响管段的几何范围) */\nexport interface ImpactArea {\n type: 'FeatureCollection';\n features: Array<\n | { type: 'Feature'; geometry: { type: 'Point'; coordinates: [number, number] }; properties: { kind: 'node' } }\n | { type: 'Feature'; geometry: { type: 'LineString'; coordinates: [number, number][] }; properties: { kind: 'pipe' } }\n >;\n /** 凸包多边形(受影响区域外轮廓) */\n hull: [number, number][];\n}\n\nexport interface BurstSimulateOptions {\n /** 风机等扩展参数:默认按气体泄漏 */\n scenario?: 'gas' | 'water' | 'drainage' | 'heating';\n /** 是否同时禁用\"已关闭阀门\"作为隔离点(推荐 true) */\n skipClosedValves?: boolean;\n /** 最大 alternative path 数 */\n maxAlternatives?: number;\n}\n\nexport interface BurstSimulateResult {\n /** 故障管段 */\n pipe: PipelinePipe;\n /** 受影响节点列表(含故障管段两端) */\n affectedNodes: PipelineNode[];\n /** 受影响管段列表 */\n affectedPipes: PipelinePipe[];\n /** 受影响用户列表 */\n affectedUsers: PipelineUser[];\n /** 受影响用户总数 */\n affectedUserCount: number;\n /** 重要用户(医院/学校/政府) */\n importantUsers: PipelineUser[];\n /** 影响区域几何(GeoJSON FeatureCollection + 凸包) */\n impactArea: ImpactArea;\n /** 阀门隔离方案 */\n valvePlan: ValvePlan;\n /** 计算耗时(ms) */\n durationMs: number;\n}\n\n/**\n * 主入口:执行爆管推演\n */\nexport function simulateBurst(\n dataset: PipelineTopologyDataset,\n pipeId: string,\n opts: BurstSimulateOptions = {}\n): BurstSimulateResult {\n const t0 = (typeof performance !== 'undefined' ? performance.now() : Date.now());\n const scenario = opts.scenario ?? 'gas';\n const skipClosed = opts.skipClosedValves ?? true;\n const maxAlt = opts.maxAlternatives ?? 2;\n\n const pipe = dataset.pipes.find((p) => p.id === pipeId);\n if (!pipe) {\n throw new Error(`BurstSimulator: pipe '${pipeId}' not found in dataset`);\n }\n const nodeById = new Map(dataset.nodes.map((n) => [n.id, n] as const));\n const adj = buildAdjacency(dataset);\n\n // 1) 沿故障 pipe 两端都搜索最近阀门(上下游)\n const upstreamValves = findValvesFromEndpoint(adj, pipe, dataset, pipe.fromNode, skipClosed);\n const downstreamValves = findValvesFromEndpoint(adj, pipe, dataset, pipe.toNode, skipClosed);\n // 合并(按距离排序去重)\n const candidateClose = mergeCandidateValves(upstreamValves, downstreamValves);\n\n // 2) 下游 BFS(PRD step 2):跳过关闭的阀门\n const closedSet = new Set(candidateClose.map((v) => v.id));\n const downstream = bfs(adj, pipe.toNode, {\n allowEdge: (_e, _f, to) => {\n if (closedSet.has(to)) return false;\n return true;\n },\n maxDepth: 1_000,\n });\n\n const affectedSet = new Set(downstream.visited);\n // 故障 pipe from/to 节点也要纳入受影响范围(事件源)\n affectedSet.add(pipe.fromNode);\n\n const affectedNodes: PipelineNode[] = [];\n for (const id of affectedSet) {\n const n = nodeById.get(id);\n if (n) affectedNodes.push(n);\n }\n\n // 受影响管段:所有至少一端在 affectedNodes 的管段\n const affectedPipes: PipelinePipe[] = dataset.pipes.filter(\n (p) => affectedSet.has(p.fromNode) || affectedSet.has(p.toNode)\n );\n\n // 3) 查询受影响用户\n const users = dataset.users ?? [];\n const affectedUsers = users.filter((u) => {\n if (!u.nodeId) return false;\n return affectedSet.has(u.nodeId);\n });\n const importantUsers = affectedUsers.filter((u) => u.kind === 'important');\n\n // 4) 影响区域几何\n const impactArea = computeImpactArea(affectedNodes, affectedPipes);\n\n // 5) 阀门隔离方案\n const valvePlan = buildValvePlan(\n adj,\n dataset,\n pipe,\n candidateClose,\n affectedNodes,\n maxAlt,\n scenario\n );\n\n const durationMs = (typeof performance !== 'undefined' ? performance.now() : Date.now()) - t0;\n return {\n pipe,\n affectedNodes,\n affectedPipes,\n affectedUsers,\n affectedUserCount: affectedUsers.length,\n importantUsers,\n impactArea,\n valvePlan,\n durationMs,\n };\n}\n\n// ============================================================\n// 内部辅助\n// ============================================================\n\ninterface ValveCandidate {\n node: PipelineNode;\n /** 距起点跳数 */\n hops: number;\n /** 距起点物理距离 */\n distance: number;\n /** 来源端 fromNode/toNode */\n endpoint: 'from' | 'to';\n}\n\n/** 从指定端点出发 BFS,沿拓扑找最近的阀门\n *\n * 关键规则:\n * - 端点本身如果是阀门 → 直接作为最近阀门返回,不再扩展\n * - 否则 BFS 找最近的阀门(找到立即停止)\n */\nfunction findValvesFromEndpoint(\n adj: AdjacencyList,\n pipe: PipelinePipe,\n dataset: PipelineTopologyDataset,\n startId: string,\n skipClosed: boolean\n): ValveCandidate[] {\n const faultPipeId = pipe.id;\n const nodeById = new Map(dataset.nodes.map((n) => [n.id, n] as const));\n const out: ValveCandidate[] = [];\n const endpoint = startId === pipe.fromNode ? 'from' : 'to';\n\n const startNode = nodeById.get(startId);\n if (!startNode) return [];\n\n // 0) 端点本身就是阀门 → 立即返回\n if (startNode.kind === 'valve') {\n if (!skipClosed || startNode.properties?.valveStatus !== 'closed') {\n out.push({ node: startNode, hops: 0, distance: 0, endpoint });\n }\n return out;\n }\n\n // 1) 否则 BFS 找最近的阀门\n const visited = new Set<string>();\n const queue: Array<{ id: string; hops: number; dist: number }> = [\n { id: startId, hops: 0, dist: 0 },\n ];\n\n while (queue.length > 0) {\n const cur = queue.shift()!;\n if (visited.has(cur.id)) continue;\n visited.add(cur.id);\n\n const n = nodeById.get(cur.id);\n if (!n) continue;\n\n if (n.kind === 'valve' && (!skipClosed || n.properties?.valveStatus !== 'closed')) {\n out.push({ node: n, hops: cur.hops, distance: cur.dist, endpoint });\n return out; // 找最近的,返回\n }\n\n const edges = adj.get(cur.id) ?? [];\n for (const e of edges) {\n if (e.pipeId === faultPipeId) continue;\n if (visited.has(e.to)) continue;\n queue.push({\n id: e.to,\n hops: cur.hops + 1,\n dist: cur.dist + (e.length || 0),\n });\n }\n }\n\n return out;\n}\n\n/** 合并上下游阀门候选(按距离排重) */\nfunction mergeCandidateValves(\n upstream: ValveCandidate[],\n downstream: ValveCandidate[]\n): PipelineNode[] {\n const seen = new Set<string>();\n const all = [...upstream, ...downstream].sort((a, b) => a.distance - b.distance);\n const out: PipelineNode[] = [];\n for (const c of all) {\n if (seen.has(c.node.id)) continue;\n seen.add(c.node.id);\n out.push(c.node);\n }\n return out;\n}\n\n/**\n * 构造影响区域\n * - features: 受影响节点(Point) + 受影响管段(LineString)\n * - hull: 节点集的凸包(用于地图高亮\"受影响地理范围\")\n */\nfunction computeImpactArea(\n nodes: PipelineNode[],\n pipes: PipelinePipe[]\n): ImpactArea {\n const features: ImpactArea['features'] = [];\n const nodeById = new Map(nodes.map((n) => [n.id, n] as const));\n\n for (const n of nodes) {\n features.push({\n type: 'Feature',\n geometry: { type: 'Point', coordinates: [n.lng, n.lat] },\n properties: { kind: 'node' },\n });\n }\n for (const p of pipes) {\n let coords: [number, number][] = [];\n if (p.geometry && p.geometry.length >= 2) {\n coords = p.geometry as [number, number][];\n } else {\n const from = nodeById.get(p.fromNode);\n const to = nodeById.get(p.toNode);\n if (from && to) coords = [[from.lng, from.lat], [to.lng, to.lat]];\n }\n if (coords.length >= 2) {\n features.push({\n type: 'Feature',\n geometry: { type: 'LineString', coordinates: coords },\n properties: { kind: 'pipe' },\n });\n }\n }\n\n const hull = convexHull(nodes.map((n) => [n.lng, n.lat] as [number, number]));\n\n return { type: 'FeatureCollection', features, hull };\n}\n\n/**\n * 构造阀门隔离方案\n */\nfunction buildValvePlan(\n adj: AdjacencyList,\n dataset: PipelineTopologyDataset,\n pipe: PipelinePipe,\n closeValves: PipelineNode[],\n _affectedNodes: PipelineNode[],\n maxAlt: number,\n scenario: string\n): ValvePlan {\n const closeSet = new Set(closeValves.map((v) => v.id));\n\n // 找泄压点:受影响区域内\"开放\"且\"不在关闭列表\"的阀门\n const openValves: PipelineNode[] = [];\n for (const n of _affectedNodes) {\n if (n.kind !== 'valve') continue;\n if (closeSet.has(n.id)) continue;\n if (n.properties?.valveStatus !== 'open') continue;\n const from = dataset.nodes.find((m) => m.id === pipe.fromNode);\n const to = dataset.nodes.find((m) => m.id === pipe.toNode);\n if (!from || !to) continue;\n const d1 = haversine(n.lng, n.lat, from.lng, from.lat);\n const d2 = haversine(n.lng, n.lat, to.lng, to.lat);\n if (Math.min(d1, d2) < 1000) openValves.push(n);\n }\n\n // 备选路径:从关闭阀门出发 → 其它 source(隔离后备用气源/水源)\n const alternativePaths: string[][] = [];\n if (closeValves.length) {\n const sources = dataset.nodes.filter((n) => n.kind === 'source');\n for (const s of sources) {\n // 选最接近关闭阀门的 source 寻路(确保目标非 closed 阀门)\n const r = dijkstra(adj, closeValves[0].id, s.id, {\n weight: (e) => (closeSet.has(e.to) ? Infinity : e.length || 1),\n });\n if (r.found) {\n const paths = findPaths(adj, closeValves[0].id, s.id, {\n maxPaths: maxAlt,\n maxDepth: 20,\n });\n for (const p of paths) alternativePaths.push(p);\n break;\n }\n }\n }\n\n // 估算停气/停水时间(基于受影响用户数和场景)\n const userCount = (dataset.users ?? []).filter((u) =>\n _affectedNodes.some((n) => n.id === u.nodeId)\n ).length;\n const baseHours = userCount / 200;\n const scenarioFactor = scenario === 'water' ? 1.5 : scenario === 'heating' ? 2 : 1;\n const hours = Math.max(0.5, Math.min(8, baseHours * scenarioFactor));\n const estimatedShutdownTime = hours >= 1 ? `${hours.toFixed(1)}h` : `${Math.round(hours * 60)}min`;\n\n const summary = buildSummary(closeValves, openValves, userCount, scenario);\n\n return {\n closeValves,\n openValves,\n alternativePaths,\n estimatedShutdownTime,\n summary,\n };\n}\n\nfunction buildSummary(\n closeValves: PipelineNode[],\n openValves: PipelineNode[],\n userCount: number,\n scenario: string\n): string {\n const labels: Record<string, string> = {\n gas: '停气',\n water: '停水',\n drainage: '排水中断',\n heating: '停热',\n };\n const label = labels[scenario] ?? '受影响';\n const parts: string[] = [];\n parts.push(`预计${label}${userCount}户`);\n if (closeValves.length) {\n parts.push(`关闭阀门 ${closeValves.map((v) => v.properties?.code ?? v.id).join(', ')}`);\n } else {\n parts.push('未找到上游隔离阀门(建议人工指定)');\n }\n if (openValves.length) {\n parts.push(`打开阀门 ${openValves.map((v) => v.properties?.code ?? v.id).join(', ')}(泄压)`);\n }\n return parts.join(';');\n}\n\n// ============================================================\n// 凸包(Andrew's monotone chain,O(n log n))\n// ============================================================\n\n/** Andrew's monotone chain,返回逆时针凸包顶点(首尾不重复) */\nexport function convexHull(points: [number, number][]): [number, number][] {\n if (points.length < 3) return [...points];\n const pts = [...points];\n pts.sort((a, b) => (a[0] - b[0]) || (a[1] - b[1]));\n\n const cross = (\n o: [number, number],\n a: [number, number],\n b: [number, number]\n ): number => (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]);\n\n const lower: [number, number][] = [];\n for (const p of pts) {\n while (lower.length >= 2 && cross(lower[lower.length - 2], lower[lower.length - 1], p) <= 0) {\n lower.pop();\n }\n lower.push(p);\n }\n const upper: [number, number][] = [];\n for (let i = pts.length - 1; i >= 0; i--) {\n const p = pts[i];\n while (upper.length >= 2 && cross(upper[upper.length - 2], upper[upper.length - 1], p) <= 0) {\n upper.pop();\n }\n upper.push(p);\n }\n upper.pop();\n lower.pop();\n return lower.concat(upper);\n}\n\n/** 用户严重程度打分(用于\"优先通告\"列表) */\nexport function userSeverity(kind: UserKind, scale = 1): number {\n const base: Record<UserKind, number> = {\n important: 100,\n industrial: 50,\n commercial: 20,\n residential: 1,\n };\n return (base[kind] ?? 1) * (scale ?? 1);\n}\n","/**\n * 阀门规划(valve planner)\n *\n * 在已知故障管段的前提下,候选出最优的\"关闭+打开\"组合。\n * 评估指标:\n * - 隔离完整性:关闭阀门后故障段必须与气源/水源完全分离\n * - 影响最小:关闭数量最小,受影响用户最少\n * - 操作便利:按操作顺序列出阀门编号\n */\n\nimport type { PipelineNode, PipelineTopologyDataset, PipelinePipe } from '../types';\nimport { buildAdjacency, type AdjacencyList } from '../graph/adjacency';\nimport { bfs } from '../graph/bfs';\nimport { dijkstra } from '../graph/shortestPath';\n\nexport interface CandidateValveSet {\n valves: PipelineNode[];\n /** 完整性:关闭后故障段到最近 source 的最短距离(Infinity = 完全隔离) */\n isolationCompleteness: number;\n /** 受影响用户数(关闭阀门后的下游覆盖) */\n impactUserCount: number;\n /** 阀门操作顺序(按节点编号字典序,仅辅助) */\n operationOrder: string[];\n}\n\nexport interface PlannerOptions {\n /** 最大候选组合数(指数爆炸时截断) */\n maxCombinations?: number;\n /** 阀门过滤:仅考虑状态/类型匹配的 */\n filter?: (valve: PipelineNode) => boolean;\n}\n\n/**\n * 列出上游候选阀门(沿故障 pipe 两端 BFS 找到的所有阀门,按距离排序)\n */\nexport function listCandidateValves(\n dataset: PipelineTopologyDataset,\n pipeId: string,\n filter?: (valve: PipelineNode) => boolean\n): PipelineNode[] {\n const pipe = dataset.pipes.find((p) => p.id === pipeId);\n if (!pipe) return [];\n const nodeById = new Map(dataset.nodes.map((n) => [n.id, n] as const));\n const adj = buildAdjacency(dataset);\n\n const visited = new Set<string>();\n const valveCandidates: Array<{ n: PipelineNode; dist: number }> = [];\n\n for (const startId of [pipe.fromNode, pipe.toNode]) {\n const queue: Array<{ id: string; d: number }> = [{ id: startId, d: 0 }];\n while (queue.length > 0) {\n const { id, d } = queue.shift()!;\n if (visited.has(id)) continue;\n visited.add(id);\n\n const n = nodeById.get(id);\n if (!n) continue;\n // 端点本身如果是阀门, 也算候选\n if (n.kind === 'valve' && (!filter || filter(n))) {\n valveCandidates.push({ n, dist: d });\n // 第一个阀门已找到, 不必继续扩展 (但允许从端点继续找其它)\n if (d > 0) continue;\n }\n\n const edges = adj.get(id) ?? [];\n for (const e of edges) {\n if (e.pipeId === pipeId) continue; // 不穿过故障 pipe\n if (visited.has(e.to)) continue;\n queue.push({ id: e.to, d: d + 1 });\n }\n }\n }\n\n valveCandidates.sort((a, b) => a.dist - b.dist);\n return valveCandidates.map((v) => v.n);\n}\n\n/**\n * 评估某组阀门关闭后的隔离完整性与受影响用户数\n */\nexport function evaluateValvePlan(\n dataset: PipelineTopologyDataset,\n pipeId: string,\n valvesToClose: PipelineNode[]\n): CandidateValveSet {\n const pipe = dataset.pipes.find((p) => p.id === pipeId);\n if (!pipe) {\n return {\n valves: valvesToClose,\n isolationCompleteness: Infinity,\n impactUserCount: 0,\n operationOrder: [],\n };\n }\n\n // 模拟\"关闭阀门 = 在邻接表中标记为不可通过\",重新计算下游覆盖\n const adj = buildAdjacency(dataset);\n const closedSet = new Set(valvesToClose.map((v) => v.id));\n const pipeById = new Map(dataset.pipes.map((p) => [p.id, p] as const));\n\n const affectedNodes = bfs(adj, pipe.toNode, {\n allowEdge: (_e, _f, to) => !closedSet.has(to),\n maxDepth: 1000,\n }).visited;\n\n // 受影响用户数\n const users = (dataset.users ?? []).filter((u) => {\n if (!u.nodeId) return false;\n return affectedNodes.includes(u.nodeId);\n });\n\n // 隔离完整性:source → 故障段 任一端 的可达性\n// 语义:所有 source 都不能绕过 closedSet 抵达 fromNode/toNode → Infinity(完全隔离)\n// 否则:completeness = source 到故障段最近的可达距离(米)\n const sources = dataset.nodes.filter((n) => n.kind === 'source');\n let completeness = Infinity;\n for (const s of sources) {\n const rTo = dijkstra(adj, s.id, pipe.toNode, {\n weight: (e) => (closedSet.has(e.to) ? Infinity : e.length || 1),\n });\n const rFrom = dijkstra(adj, s.id, pipe.fromNode, {\n weight: (e) => (closedSet.has(e.to) ? Infinity : e.length || 1),\n });\n const reachable =\n rTo.found ? rTo.distance : Infinity;\n const reachableFrom =\n rFrom.found ? rFrom.distance : Infinity;\n const nearest = Math.min(reachable, reachableFrom);\n if (nearest < completeness) completeness = nearest;\n }\n\n const order = valvesToClose\n .map((v) => v.properties?.code ?? v.id)\n .sort();\n\n return {\n valves: valvesToClose,\n isolationCompleteness: completeness,\n impactUserCount: users.length,\n operationOrder: order,\n };\n}\n","/**\n * 影响区域 helpers\n *\n * 把 BurstSimulator 输出的受影响节点+管段渲染成 MapLibre 图层用的 GeoJSON。\n */\n\nimport type { BurstSimulateResult } from './burstCore';\nimport type { PipelineNode, PipelinePipe } from '../types';\n\nexport interface MapLayerData {\n /** 受影响区域凸包多边形(用于高亮) */\n hullPolygon: GeoJSON.Feature<\n GeoJSON.Polygon,\n { score: number; affected: number }\n > | null;\n /** 受影响管段 LineString 集合(用于粗化红色线) */\n affectedPipes: GeoJSON.FeatureCollection<\n GeoJSON.LineString,\n { pipeId: string; scenario: string }\n >;\n /** 受影响节点 Point 集合 */\n affectedNodes: GeoJSON.FeatureCollection<\n GeoJSON.Point,\n { nodeId: string; kind: string }\n >;\n}\n\n/**\n * 把 BurstSimulateResult 映射为地图图层数据\n */\nexport function toMapLayerData(result: BurstSimulateResult): MapLayerData {\n const hull = result.impactArea.hull;\n const hullPolygon: MapLayerData['hullPolygon'] = hull.length >= 3\n ? {\n type: 'Feature',\n geometry: { type: 'Polygon', coordinates: [hull] },\n properties: { score: 1, affected: result.affectedUserCount },\n }\n : null;\n\n // 构造 node 坐标索引以便退化几何\n const nodeCoords = new Map<string, { lng: number; lat: number }>();\n for (const n of result.affectedNodes) nodeCoords.set(n.id, n);\n\n const affectedPipes: GeoJSON.FeatureCollection<GeoJSON.LineString, { pipeId: string; scenario: string }> = {\n type: 'FeatureCollection',\n features: result.affectedPipes\n .map((p) => ({\n type: 'Feature' as const,\n geometry: pipeToLineString(p, nodeCoords),\n properties: { pipeId: p.id, scenario: 'affected' },\n }))\n .filter((f) => f.geometry.coordinates.length >= 2),\n };\n\n const affectedNodes: GeoJSON.FeatureCollection<GeoJSON.Point, { nodeId: string; kind: string }> = {\n type: 'FeatureCollection',\n features: result.affectedNodes.map((n) => ({\n type: 'Feature' as const,\n geometry: { type: 'Point', coordinates: [n.lng, n.lat] },\n properties: { nodeId: n.id, kind: n.kind },\n })),\n };\n\n return { hullPolygon, affectedPipes, affectedNodes };\n}\n\nfunction pipeToLineString(p: PipelinePipe, nodes: Map<string, { lng: number; lat: number }>): GeoJSON.LineString {\n if (p.geometry && p.geometry.length >= 2) {\n return { type: 'LineString', coordinates: p.geometry as [number, number][] };\n }\n // 退化:从端点拉直线\n const from = nodes.get(p.fromNode);\n const to = nodes.get(p.toNode);\n if (from && to) {\n return {\n type: 'LineString',\n coordinates: [\n [from.lng, from.lat],\n [to.lng, to.lat],\n ],\n };\n }\n return { type: 'LineString', coordinates: [] };\n}\n\n/** 计算受影响区域总面积(使用 shoelace 公式) */\nexport function impactAreaSquareMeters(hull: [number, number][]): number {\n if (hull.length < 3) return 0;\n // 把经纬度局部转米(以第一个点为原点,使用等距近似)\n const refLat = hull[0][1];\n const mPerDegLat = 110_540;\n const mPerDegLng = 111_320 * Math.cos((refLat * Math.PI) / 180);\n\n const pts = hull.map(([lng, lat]) => [\n (lng - hull[0][0]) * mPerDegLng,\n (lat - hull[0][1]) * mPerDegLat,\n ]);\n\n let sum = 0;\n for (let i = 0; i < pts.length; i++) {\n const [x1, y1] = pts[i];\n const [x2, y2] = pts[(i + 1) % pts.length];\n sum += x1 * y2 - x2 * y1;\n }\n return Math.abs(sum) / 2;\n}\n\n/** 估算受影响节点的\"中心点\"(用于地图 flyTo) */\nexport function impactCenter(nodes: PipelineNode[]): [number, number] | null {\n if (!nodes.length) return null;\n let lng = 0;\n let lat = 0;\n for (const n of nodes) {\n lng += n.lng;\n lat += n.lat;\n }\n return [lng / nodes.length, lat / nodes.length];\n}\n\n/** 从管段上取最近的节点(用于点击管线后弹出该节点信息卡) */\nexport function nearestNodeOnPipe(\n pipe: PipelinePipe,\n nodes: PipelineNode[],\n lng: number,\n lat: number\n): PipelineNode | null {\n const a = nodes.find((n) => n.id === pipe.fromNode);\n const b = nodes.find((n) => n.id === pipe.toNode);\n if (!a || !b) return null;\n const da = haversineApprox(a.lng, a.lat, lng, lat);\n const db = haversineApprox(b.lng, b.lat, lng, lat);\n return da < db ? a : b;\n}\n\nfunction haversineApprox(lng1: number, lat1: number, lng2: number, lat2: number): number {\n const dx = (lng2 - lng1) * 111_320 * Math.cos((lat1 * Math.PI) / 180);\n const dy = (lat2 - lat1) * 110_540;\n return Math.sqrt(dx * dx + dy * dy);\n}\n","/**\n * BurstSimulator 组件类(地图集成层)\n *\n * 包装 simulateBurst 纯函数 + 维护 MapLibre 图层状态。\n * 组件层职责:\n * - 接收地图实例,添加受影响区域/管段/阀门、方案侧栏\n * - 暴露 simulate()、clear() 等命令式 API\n * - 可订阅结果事件(affectedNodes/valvePlan/impactArea)\n *\n * 注意:此组件不直接依赖 Vue/React(业务方可在任意框架中实例化)\n */\n\nimport type { Map as CaoguoMap } from '@caoguo/maplibre';\nimport {\n simulateBurst,\n type BurstSimulateOptions,\n type BurstSimulateResult,\n} from './burstCore';\nimport { toMapLayerData } from './impactArea';\nimport type { PipelineTopologyDataset, PipelineType } from '../types';\n\nexport interface BurstSimulatorOptions {\n map: CaoguoMap;\n dataset: PipelineTopologyDataset;\n /** 受影响管段样式(maplibre paint props) */\n affectedPipePaint?: Record<string, unknown>;\n /** 阀门隔离方案样式 */\n valvePaint?: Record<string, unknown>;\n /** 影响区域凸包样式 */\n hullPaint?: Record<string, unknown>;\n /** 受影响节点图标样式 */\n affectedNodePaint?: Record<string, unknown>;\n /** 推演情景 */\n scenario?: BurstSimulateOptions['scenario'];\n /** 该实例只处理指定管线类型(用于多管类地图) */\n pipelineType?: PipelineType;\n /** 层 ID 前缀(避免多实例冲突) */\n layerPrefix?: string;\n}\n\nexport type BurstResult = BurstSimulateResult;\n\ntype Listener = (r: BurstSimulateResult) => void;\n\n/**\n * 爆管推演组件(前端类)\n *\n * 用法:\n * const sim = new BurstSimulator({ map, dataset });\n * const result = sim.simulate('pipe-A12');\n * // 受影响区域已添加到 map\n * sim.clear();\n * sim.destroy();\n */\nexport class BurstSimulator {\n private map: CaoguoMap;\n private dataset: PipelineTopologyDataset;\n private scenario: 'gas' | 'water' | 'drainage' | 'heating';\n private affectedPipePaint: Record<string, unknown>;\n private affectedNodePaint: Record<string, unknown>;\n private valvePaint: Record<string, unknown>;\n private hullPaint: Record<string, unknown>;\n private layerPrefix: string;\n private listeners = new Set<Listener>();\n private lastResult: BurstSimulateResult | null = null;\n private layerIds: string[] = [];\n\n constructor(options: BurstSimulatorOptions) {\n this.map = options.map;\n this.dataset = options.dataset;\n this.scenario = options.scenario ?? 'gas';\n this.affectedPipePaint = options.affectedPipePaint ?? {\n 'line-color': '#ef4444',\n 'line-width': 4,\n 'line-opacity': 0.85,\n 'line-blur': 1.5,\n };\n this.affectedNodePaint = options.affectedNodePaint ?? {\n 'circle-radius': 6,\n 'circle-color': '#ef4444',\n 'circle-stroke-width': 2,\n 'circle-stroke-color': '#ffffff',\n };\n this.valvePaint = options.valvePaint ?? {\n 'circle-radius': 8,\n 'circle-color': '#fbbf24',\n 'circle-stroke-width': 2,\n 'circle-stroke-color': '#000000',\n };\n this.hullPaint = options.hullPaint ?? {\n 'fill-color': '#ef4444',\n 'fill-opacity': 0.15,\n 'fill-outline-color': '#ef4444',\n };\n this.layerPrefix = options.layerPrefix ?? 'cg-burst';\n }\n\n /** 触发爆管推演 */\n simulate(pipeId: string, overrideOpts?: BurstSimulateOptions): BurstSimulateResult {\n const result = simulateBurst(this.dataset, pipeId, {\n scenario: overrideOpts?.scenario ?? this.scenario,\n skipClosedValves: overrideOpts?.skipClosedValves ?? true,\n maxAlternatives: overrideOpts?.maxAlternatives ?? 2,\n });\n this.lastResult = result;\n this.render(result);\n for (const l of this.listeners) l(result);\n return result;\n }\n\n /** 清空所有受影响区域图层 */\n clear(): void {\n for (const id of this.layerIds) {\n this.map.removeLayer(id);\n }\n this.layerIds = [];\n }\n\n /** 销毁并清空所有资源 */\n destroy(): void {\n this.clear();\n this.listeners.clear();\n this.lastResult = null;\n }\n\n /** 订阅推演结果 */\n onResult(fn: Listener): () => void {\n this.listeners.add(fn);\n return () => this.listeners.delete(fn);\n }\n\n /** 取最后一次结果 */\n getLastResult(): BurstSimulateResult | null {\n return this.lastResult;\n }\n\n // ------------------------------------------------------\n // 内部:把结果渲染为 MapLibre 图层\n // ------------------------------------------------------\n private render(result: BurstSimulateResult): void {\n this.clear();\n const layerData = toMapLayerData(result);\n const mlMap = (this.map as unknown as {\n instance: {\n addSource: (id: string, source: unknown) => void;\n addLayer: (layer: unknown) => void;\n getSource: (id: string) => unknown;\n };\n }).instance;\n\n const prefix = this.layerPrefix;\n const sourcesToAdd: Array<{ id: string; data: unknown }> = [];\n const layersToAdd: Array<Record<string, unknown>> = [];\n\n if (layerData.hullPolygon) {\n sourcesToAdd.push({ id: `${prefix}-hull-src`, data: layerData.hullPolygon });\n layersToAdd.push({\n id: `${prefix}-hull-fill`,\n type: 'fill',\n source: `${prefix}-hull-src`,\n paint: this.hullPaint,\n });\n }\n\n sourcesToAdd.push({ id: `${prefix}-pipes-src`, data: layerData.affectedPipes });\n layersToAdd.push({\n id: `${prefix}-pipes-line`,\n type: 'line',\n source: `${prefix}-pipes-src`,\n paint: this.affectedPipePaint,\n });\n\n sourcesToAdd.push({ id: `${prefix}-nodes-src`, data: layerData.affectedNodes });\n layersToAdd.push({\n id: `${prefix}-nodes-pt`,\n type: 'circle',\n source: `${prefix}-nodes-src`,\n paint: this.affectedNodePaint,\n });\n\n for (const src of sourcesToAdd) {\n if (!mlMap.getSource(src.id)) mlMap.addSource(src.id, src.data as never);\n }\n for (const layer of layersToAdd) {\n try {\n mlMap.addLayer(layer);\n this.layerIds.push(layer.id as string);\n } catch {\n // ignore duplicate\n }\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/graph/adjacency.ts","../../src/graph/bfs.ts","../../src/graph/shortestPath.ts","../../src/graph/connectivity.ts","../../src/burst/burstCore.ts","../../src/burst/valvePlanner.ts","../../src/burst/impactArea.ts","../../src/burst/burstClass.ts"],"names":["cur"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * 图邻接表构建(管线拓扑 → 双向邻接表)\n *\n * 输入:管网拓扑数据集(节点 + 管段)\n * 输出:邻接表 Map<nodeId, Edge[]>\n *\n * Phase 1 图遍历的入口:把物理拓扑转换为图论可用的数据结构。\n */\n\nimport type {\n PipelineNode,\n PipelinePipe,\n PipelineTopologyDataset,\n} from '../types';\n\n/**\n * 邻接表中的\"边\"\n * - 物理上一条 pipe 是两个 node 之间的连接\n * - 邻接表中记录:pipeId、邻居节点 id、长度等\n */\nexport interface AdjEdge {\n pipeId: string;\n /** 邻居节点 id(沿此边走一步到达) */\n to: string;\n /** 长度(m),无则 0 */\n length: number;\n /** 阻力/权重(用于复杂路径优选,可选) */\n weight?: number;\n}\n\n/** 邻接表:Map<nodeId, AdjEdge[]> */\nexport type AdjacencyList = Map<string, AdjEdge[]>;\n\n/**\n * 从 PipelineTopologyDataset 构建邻接表\n */\nexport function buildAdjacency(dataset: PipelineTopologyDataset): AdjacencyList {\n const adj: AdjacencyList = new Map();\n\n // 初始化所有节点(防止孤立点不出现)\n for (const node of dataset.nodes) {\n if (!adj.has(node.id)) adj.set(node.id, []);\n }\n\n for (const pipe of dataset.pipes) {\n const len = pipe.length ?? pipeLengthFromGeometry(pipe, dataset.nodes) ?? 0;\n\n const fromList = adj.get(pipe.fromNode) ?? [];\n fromList.push({\n pipeId: pipe.id,\n to: pipe.toNode,\n length: len,\n });\n adj.set(pipe.fromNode, fromList);\n\n const toList = adj.get(pipe.toNode) ?? [];\n toList.push({\n pipeId: pipe.id,\n to: pipe.fromNode,\n length: len,\n });\n adj.set(pipe.toNode, toList);\n }\n\n return adj;\n}\n\n/**\n * 计算单条 pipe 长度(haversine)\n * 若 pipe 提供 geometry 则累计几何点距离,否则按 from-to 直线长度。\n */\nexport function pipeLengthFromGeometry(\n pipe: PipelinePipe,\n nodes: PipelineNode[]\n): number {\n if (pipe.length && pipe.length > 0) return pipe.length;\n if (pipe.geometry && pipe.geometry.length >= 2) {\n let total = 0;\n for (let i = 1; i < pipe.geometry.length; i++) {\n total += haversine(\n pipe.geometry[i - 1][0],\n pipe.geometry[i - 1][1],\n pipe.geometry[i][0],\n pipe.geometry[i][1]\n );\n }\n return total;\n }\n const from = nodes.find((n) => n.id === pipe.fromNode);\n const to = nodes.find((n) => n.id === pipe.toNode);\n if (!from || !to) return 0;\n return haversine(from.lng, from.lat, to.lng, to.lat);\n}\n\n/** Haversine 距离(m) */\nexport function haversine(\n lng1: number,\n lat1: number,\n lng2: number,\n lat2: number\n): number {\n const R = 6_371_000;\n const toRad = (d: number) => (d * Math.PI) / 180;\n const dLat = toRad(lat2 - lat1);\n const dLng = toRad(lng2 - lng1);\n const a =\n Math.sin(dLat / 2) ** 2 +\n Math.cos(toRad(lat1)) *\n Math.cos(toRad(lat2)) *\n Math.sin(dLng / 2) ** 2;\n return 2 * R * Math.asin(Math.sqrt(a));\n}\n\n/** 从邻接表拿指定节点的邻居 id 列表(去重) */\nexport function neighborIds(adj: AdjacencyList, nodeId: string): string[] {\n const list = adj.get(nodeId) ?? [];\n const seen = new Set<string>();\n const out: string[] = [];\n for (const e of list) {\n if (!seen.has(e.to)) {\n seen.add(e.to);\n out.push(e.to);\n }\n }\n return out;\n}\n\n/** 取出指定节点的所有边 */\nexport function edgesOf(adj: AdjacencyList, nodeId: string): AdjEdge[] {\n return adj.get(nodeId) ?? [];\n}\n","/**\n * BFS(广度优先遍历)\n *\n * 用途:\n * - 爆管推演:下游影响范围(沿拓扑扩散)\n * - 连通性查询:在指定层级内查找可达节点\n *\n * 实现要点:\n * - 支持 visited / parents 记录\n * - 支持 maxDepth 限制(避免极大连通分量过长)\n * - 支持 predicate 过滤可继续遍历的邻居\n * - 可返回\"沿途经过的管段\"列表(用于前端高亮)\n */\n\nimport type { AdjacencyList, AdjEdge } from './adjacency';\n\nexport interface BfsResult {\n /** 访问过的节点(不重复) */\n visited: string[];\n /** 父节点表:node -> 上一步到达的 node(首节点为自身) */\n parents: Map<string, string | null>;\n /** 起点 节点 */\n start: string;\n /** 终点节点(搜到即停,返回时 visited 是到终点为止的节点) */\n end?: string;\n}\n\nexport interface BfsOptions {\n /** 最大深度(边数),默认无限制 */\n maxDepth?: number;\n /** 是否指定终点(BFS 找到则停止) */\n until?: (node: string) => boolean;\n /** 在扩展邻居前过滤:false 则该方向不继续遍历 */\n allowEdge?: (edge: AdjEdge, from: string, to: string) => boolean;\n /** 起点本身的过滤器(如只走下游/上游) */\n allowStart?: (node: string) => boolean;\n}\n\n/**\n * 标准 BFS,可指定\"任意邻居是否可达\"\n *\n * 用法:\n * const r = bfs(adj, 'node-A');\n * bfs(adj, 'start', { until: (n) => n === 'target' }); // 找终点\n * bfs(adj, 'start', { allowEdge: (_, __, to) => to !== 'forbidden' });\n */\nexport function bfs(\n adj: AdjacencyList,\n start: string,\n opts: BfsOptions = {}\n): BfsResult {\n const visited: string[] = [];\n const parents = new Map<string, string | null>();\n const visitedSet = new Set<string>();\n\n if (!adj.has(start)) {\n parents.set(start, null);\n return { visited, parents, start };\n }\n\n if (opts.allowStart && !opts.allowStart(start)) {\n return { visited: [], parents, start };\n }\n\n const queue: Array<{ id: string; depth: number }> = [{ id: start, depth: 0 }];\n parents.set(start, null);\n visitedSet.add(start);\n visited.push(start);\n\n let foundEnd: string | undefined;\n while (queue.length > 0) {\n const { id, depth } = queue.shift()!;\n\n if (opts.until && opts.until(id)) {\n foundEnd = id;\n break;\n }\n\n // maxDepth 语义:最多走 N 条边,到达节点的最短路径长度为 N\n // 当前节点 depth=d = 经过 d 条边到达,扩展邻居须 depth+1 <= maxDepth\n if (opts.maxDepth !== undefined && depth >= opts.maxDepth) continue;\n\n const edges = adj.get(id) ?? [];\n for (const e of edges) {\n if (opts.allowEdge && !opts.allowEdge(e, id, e.to)) continue;\n if (visitedSet.has(e.to)) continue;\n visitedSet.add(e.to);\n parents.set(e.to, id);\n visited.push(e.to);\n queue.push({ id: e.to, depth: depth + 1 });\n }\n }\n\n return { visited, parents, start, end: foundEnd };\n}\n\n/**\n * 多源 BFS(同时从多个起点扩散)\n *\n * 用法:爆管分析的下游影响可从多点同时推演(如多个隔离阀门的下游剩余服务区)\n */\nexport function multiSourceBfs(\n adj: AdjacencyList,\n starts: string[],\n opts: BfsOptions = {}\n): BfsResult & { sourceMap: Map<string, string> } {\n const visited: string[] = [];\n const parents = new Map<string, string | null>();\n const sourceMap = new Map<string, string>();\n const visitedSet = new Set<string>();\n\n const queue: Array<{ id: string; depth: number }> = [];\n\n for (const s of starts) {\n if (!adj.has(s)) continue;\n if (opts.allowStart && !opts.allowStart(s)) continue;\n if (!visitedSet.has(s)) {\n visitedSet.add(s);\n parents.set(s, null);\n sourceMap.set(s, s);\n visited.push(s);\n queue.push({ id: s, depth: 0 });\n }\n }\n\n while (queue.length > 0) {\n const { id, depth } = queue.shift()!;\n // 同单源 BFS:depth=d 时扩展邻居;maxDepth=N 表示最多 N 条边\n if (opts.maxDepth !== undefined && depth >= opts.maxDepth) continue;\n\n const edges = adj.get(id) ?? [];\n for (const e of edges) {\n if (opts.allowEdge && !opts.allowEdge(e, id, e.to)) continue;\n if (visitedSet.has(e.to)) continue;\n visitedSet.add(e.to);\n parents.set(e.to, id);\n sourceMap.set(e.to, sourceMap.get(id)!);\n visited.push(e.to);\n queue.push({ id: e.to, depth: depth + 1 });\n }\n }\n\n return { visited, parents, start: starts[0] ?? '', sourceMap };\n}\n\n/**\n * 反向 BFS(沿父指针回溯)\n *\n * 给定终点 + parents Map,可还原 BFS 路径(用于\"找到的最短路径\")。\n */\nexport function reconstructPath(\n parents: Map<string, string | null>,\n end: string\n): string[] {\n const path: string[] = [];\n let cur: string | null = end;\n while (cur) {\n path.unshift(cur);\n const p = parents.get(cur);\n cur = p ?? null;\n if (cur === null && p === null) {\n // 起点到达\n if (parents.get(end) === null && path.length === 1) break;\n break;\n }\n }\n if (path[0] !== end) {\n // already include end correctly\n }\n return path;\n}\n","/**\n * 最短路径(Dijkstra)\n *\n * 用途:\n * - 上游距离最近的阀门定位\n * - 备选供气/供水路径(按管径/压力选优)\n */\n\nimport type { AdjacencyList, AdjEdge } from './adjacency';\n\nexport interface ShortestPathResult {\n distance: number;\n path: string[];\n found: boolean;\n}\n\nexport interface ShortestPathOptions {\n /** 边权重函数:默认 1 */\n weight?: (edge: AdjEdge) => number;\n /** 提前终止:找到满足条件的节点立即返回 */\n until?: (node: string, dist: number) => boolean;\n}\n\n/**\n * Dijkstra 最短路径\n *\n * 注意:当存在负权边时不可用;管网场景边权重非负,管长/管径均适用。\n */\nexport function dijkstra(\n adj: AdjacencyList,\n start: string,\n end: string,\n opts: ShortestPathOptions = {}\n): ShortestPathResult {\n if (!adj.has(start) || !adj.has(end)) {\n return { distance: Infinity, path: [], found: false };\n }\n\n const weight = opts.weight ?? ((e: AdjEdge) => e.length || 1);\n\n const dist = new Map<string, number>();\n const parents = new Map<string, string | null>();\n const visited = new Set<string>();\n const pq: Array<{ id: string; d: number }> = [{ id: start, d: 0 }];\n\n for (const n of adj.keys()) {\n dist.set(n, Infinity);\n parents.set(n, null);\n }\n dist.set(start, 0);\n\n while (pq.length > 0) {\n // 简化:线性查找最小值(小图足够;大规模可换二叉堆)\n pq.sort((a, b) => a.d - b.d);\n const cur = pq.shift()!;\n if (visited.has(cur.id)) continue;\n visited.add(cur.id);\n if (cur.id === end) break;\n\n const edges = adj.get(cur.id) ?? [];\n for (const e of edges) {\n if (visited.has(e.to)) continue;\n const w = weight(e);\n const alt = (dist.get(cur.id) ?? Infinity) + w;\n if (alt < (dist.get(e.to) ?? Infinity)) {\n dist.set(e.to, alt);\n parents.set(e.to, cur.id);\n pq.push({ id: e.to, d: alt });\n }\n }\n\n if (opts.until && opts.until(cur.id, cur.d)) break;\n }\n\n if ((dist.get(end) ?? Infinity) === Infinity) {\n return { distance: Infinity, path: [], found: false };\n }\n\n // 回溯路径\n const path: string[] = [];\n let cur: string | null = end;\n while (cur) {\n path.unshift(cur);\n const p = parents.get(cur);\n if (p === undefined) break;\n cur = p;\n }\n\n return { distance: dist.get(end) ?? 0, path, found: true };\n}\n","/**\n * 连通性分析\n *\n * 用途:\n * - P-4 连通性高亮:选中管线后高亮上下游连通路径\n * - 健康评估的影响范围计算\n * - 用户问\"阀门X关闭后影响哪些小区?\"\n */\n\nimport type { AdjacencyList, AdjEdge } from './adjacency';\nimport { bfs } from './bfs';\nimport type { PipelineNode, PipelineTopologyDataset, NodeKind } from '../types';\n\n/**\n * 连通分量(连通子图)\n */\nexport interface ConnectedComponent {\n /** 节点集合 */\n nodes: string[];\n /** 节点数 */\n size: number;\n /** 是否包含 source 类型节点(影响气源/水源判定) */\n hasSource: boolean;\n}\n\n/**\n * 求所有连通分量\n */\nexport function findConnectedComponents(\n adj: AdjacencyList,\n nodes: PipelineNode[]\n): ConnectedComponent[] {\n const visited = new Set<string>();\n const components: ConnectedComponent[] = [];\n\n const kindById = new Map<string, NodeKind>();\n for (const n of nodes) kindById.set(n.id, n.kind);\n\n for (const nodeId of adj.keys()) {\n if (visited.has(nodeId)) continue;\n const r = bfs(adj, nodeId);\n let hasSource = false;\n for (const id of r.visited) {\n visited.add(id);\n if (kindById.get(id) === 'source') hasSource = true;\n }\n components.push({\n nodes: r.visited,\n size: r.visited.length,\n hasSource,\n });\n }\n\n return components;\n}\n\n/**\n * 找到两个节点之间的所有路径(k 短路)\n *\n * 用途:阀门隔离方案中\"备选路径\"分析\n * NOTE:DFS+Yen's 算法简化版,路径数 < 10 适用。\n */\nexport function findPaths(\n adj: AdjacencyList,\n start: string,\n end: string,\n opts: { maxPaths?: number; maxDepth?: number } = {}\n): string[][] {\n const maxPaths = opts.maxPaths ?? 3;\n const maxDepth = opts.maxDepth ?? 20;\n\n const all: string[][] = [];\n const path: string[] = [];\n const onPath = new Set<string>();\n\n const dfsLocal = (cur: string) => {\n if (all.length >= maxPaths) return;\n if (cur === end) {\n all.push([...path]);\n return;\n }\n if (path.length >= maxDepth) return;\n onPath.add(cur);\n path.push(cur);\n const edges = adj.get(cur) ?? [];\n for (const e of edges) {\n if (onPath.has(e.to)) continue;\n dfsLocal(e.to);\n if (all.length >= maxPaths) return;\n }\n path.pop();\n onPath.delete(cur);\n };\n\n dfsLocal(start);\n return all;\n}\n\n/**\n * 沿拓扑向上游找到最近的指定类型节点(默认阀门)\n *\n * 用途:爆管推演自动定位隔离点(PRD §4.2.4 step 1)\n *\n * 说明:管网拓扑在无流向数据时是无向图。本实现从故障管段起点向上游\n * 广度搜索,并避免沿\"刚走过的同一管段\"原路返回,从而向远离故障点的\n * 上游方向收敛,命中 predicate(如阀门)即停。\n */\nexport function findUpstreamNode(\n adj: AdjacencyList,\n startPipeId: string,\n dataset: PipelineTopologyDataset,\n predicate: (n: PipelineNode) => boolean\n): PipelineNode | null {\n const pipe = dataset.pipes.find((p) => p.id === startPipeId);\n if (!pipe) return null;\n\n const nodeById = new Map(dataset.nodes.map((n) => [n.id, n]));\n\n // 起始:选择 fromNode 作为查找起点(故障管段上游侧)\n const startId = pipe.fromNode;\n if (!nodeById.has(startId)) return null;\n\n // 向上游游走:禁止沿\"刚走过的同一管段\"原路返回,避免来回打转\n const allowEdge = (e: AdjEdge, _from: string, _to: string) => {\n return e.pipeId !== startPipeId;\n };\n\n // BFS 到上游直到命中 predicate\n const r = bfs(adj, startId, {\n allowEdge,\n until: (n) => {\n const node = nodeById.get(n);\n return node ? predicate(node) : false;\n },\n maxDepth: 50,\n });\n\n if (!r.end) return null;\n return nodeById.get(r.end) ?? null;\n}\n\n/**\n * 高亮连通路径(从起点 BFS,把沿途所有 pipe 收集起来)\n *\n * 用途:选中管段/节点 → 高亮上下游\n */\nexport function highlightConnectivity(\n adj: AdjacencyList,\n start: string\n): { nodeIds: Set<string>; edgeIds: Set<string> } {\n const r = bfs(adj, start, { maxDepth: 64 });\n const nodeIds = new Set(r.visited);\n const edgeIds = new Set<string>();\n\n for (const n of r.visited) {\n const edges = adj.get(n) ?? [];\n for (const e of edges) {\n // 只高亮两端都已访问的边\n if (nodeIds.has(e.to)) edgeIds.add(e.pipeId);\n }\n }\n\n return { nodeIds, edgeIds };\n}\n","/**\n * BurstSimulator 核心算法(纯函数)\n *\n * 模拟\"故障管段\"后:\n * 1. 找所有隔离候选阀门(沿故障 pipe 任意一端 BFS,候选上、下游最近阀门)\n * 2. 至少保留:上游最近阀门 + 下游最近阀门,确保\"故障段完全与气源/水源分离\"\n * 3. 下游 BFS(同时绕过被关闭阀门)找受影响节点\n * 4. 关联受影响用户(居民/商业/工业)\n * 5. 重要用户识别(医院/学校/工厂)\n * 6. 备选供气/供水路径(Dijkstra)\n *\n * 全部为纯函数,接收数据集返回结果,可在 Node/浏览器两侧运行。\n */\n\nimport type {\n PipelineTopologyDataset,\n PipelineNode,\n PipelinePipe,\n PipelineUser,\n UserKind,\n} from '../types';\nimport {\n buildAdjacency,\n type AdjacencyList,\n haversine,\n} from '../graph/adjacency';\nimport { bfs } from '../graph/bfs';\nimport { dijkstra } from '../graph/shortestPath';\nimport { findPaths } from '../graph/connectivity';\n\n/** 阀门隔离方案 */\nexport interface ValvePlan {\n /** 需关闭的阀门(隔离故障段) */\n closeValves: PipelineNode[];\n /** 需打开的阀门(泄压/排水) */\n openValves: PipelineNode[];\n /** 备选供气/供水路径(多源时才有) */\n alternativePaths: string[][];\n /** 预计停气/停水时间字符串(如 \"2h\"、\"45min\") */\n estimatedShutdownTime: string;\n /** 隔离方案的可读摘要 */\n summary: string;\n}\n\n/** 影响区域(受影响管段的几何范围) */\nexport interface ImpactArea {\n type: 'FeatureCollection';\n features: Array<\n | { type: 'Feature'; geometry: { type: 'Point'; coordinates: [number, number] }; properties: { kind: 'node' } }\n | { type: 'Feature'; geometry: { type: 'LineString'; coordinates: [number, number][] }; properties: { kind: 'pipe' } }\n >;\n /** 凸包多边形(受影响区域外轮廓) */\n hull: [number, number][];\n}\n\nexport interface BurstSimulateOptions {\n /** 风机等扩展参数:默认按气体泄漏 */\n scenario?: 'gas' | 'water' | 'drainage' | 'heating';\n /** 是否同时禁用\"已关闭阀门\"作为隔离点(推荐 true) */\n skipClosedValves?: boolean;\n /** 最大 alternative path 数 */\n maxAlternatives?: number;\n}\n\nexport interface BurstSimulateResult {\n /** 故障管段 */\n pipe: PipelinePipe;\n /** 受影响节点列表(含故障管段两端) */\n affectedNodes: PipelineNode[];\n /** 受影响管段列表 */\n affectedPipes: PipelinePipe[];\n /** 受影响用户列表 */\n affectedUsers: PipelineUser[];\n /** 受影响用户总数 */\n affectedUserCount: number;\n /** 重要用户(医院/学校/政府) */\n importantUsers: PipelineUser[];\n /** 影响区域几何(GeoJSON FeatureCollection + 凸包) */\n impactArea: ImpactArea;\n /** 阀门隔离方案 */\n valvePlan: ValvePlan;\n /** 计算耗时(ms) */\n durationMs: number;\n}\n\n/**\n * 主入口:执行爆管推演\n */\nexport function simulateBurst(\n dataset: PipelineTopologyDataset,\n pipeId: string,\n opts: BurstSimulateOptions = {}\n): BurstSimulateResult {\n const t0 = (typeof performance !== 'undefined' ? performance.now() : Date.now());\n const scenario = opts.scenario ?? 'gas';\n const skipClosed = opts.skipClosedValves ?? true;\n const maxAlt = opts.maxAlternatives ?? 2;\n\n const pipe = dataset.pipes.find((p) => p.id === pipeId);\n if (!pipe) {\n throw new Error(`BurstSimulator: pipe '${pipeId}' not found in dataset`);\n }\n const nodeById = new Map(dataset.nodes.map((n) => [n.id, n] as const));\n const adj = buildAdjacency(dataset);\n\n // 1) 沿故障 pipe 两端都搜索最近阀门(上下游)\n const upstreamValves = findValvesFromEndpoint(adj, pipe, dataset, pipe.fromNode, skipClosed);\n const downstreamValves = findValvesFromEndpoint(adj, pipe, dataset, pipe.toNode, skipClosed);\n // 合并(按距离排序去重)\n const candidateClose = mergeCandidateValves(upstreamValves, downstreamValves);\n\n // 2) 下游 BFS(PRD step 2):跳过关闭的阀门\n const closedSet = new Set(candidateClose.map((v) => v.id));\n const downstream = bfs(adj, pipe.toNode, {\n allowEdge: (_e, _f, to) => {\n if (closedSet.has(to)) return false;\n return true;\n },\n maxDepth: 1_000,\n });\n\n const affectedSet = new Set(downstream.visited);\n // 故障 pipe from/to 节点也要纳入受影响范围(事件源)\n affectedSet.add(pipe.fromNode);\n\n const affectedNodes: PipelineNode[] = [];\n for (const id of affectedSet) {\n const n = nodeById.get(id);\n if (n) affectedNodes.push(n);\n }\n\n // 受影响管段:所有至少一端在 affectedNodes 的管段\n const affectedPipes: PipelinePipe[] = dataset.pipes.filter(\n (p) => affectedSet.has(p.fromNode) || affectedSet.has(p.toNode)\n );\n\n // 3) 查询受影响用户\n const users = dataset.users ?? [];\n const affectedUsers = users.filter((u) => {\n if (!u.nodeId) return false;\n return affectedSet.has(u.nodeId);\n });\n const importantUsers = affectedUsers.filter((u) => u.kind === 'important');\n\n // 4) 影响区域几何\n const impactArea = computeImpactArea(affectedNodes, affectedPipes);\n\n // 5) 阀门隔离方案\n const valvePlan = buildValvePlan(\n adj,\n dataset,\n pipe,\n candidateClose,\n affectedNodes,\n maxAlt,\n scenario\n );\n\n const durationMs = (typeof performance !== 'undefined' ? performance.now() : Date.now()) - t0;\n return {\n pipe,\n affectedNodes,\n affectedPipes,\n affectedUsers,\n affectedUserCount: affectedUsers.length,\n importantUsers,\n impactArea,\n valvePlan,\n durationMs,\n };\n}\n\n// ============================================================\n// 内部辅助\n// ============================================================\n\ninterface ValveCandidate {\n node: PipelineNode;\n /** 距起点跳数 */\n hops: number;\n /** 距起点物理距离 */\n distance: number;\n /** 来源端 fromNode/toNode */\n endpoint: 'from' | 'to';\n}\n\n/** 从指定端点出发 BFS,沿拓扑找最近的阀门\n *\n * 关键规则:\n * - 端点本身如果是阀门 → 直接作为最近阀门返回,不再扩展\n * - 否则 BFS 找最近的阀门(找到立即停止)\n */\nfunction findValvesFromEndpoint(\n adj: AdjacencyList,\n pipe: PipelinePipe,\n dataset: PipelineTopologyDataset,\n startId: string,\n skipClosed: boolean\n): ValveCandidate[] {\n const faultPipeId = pipe.id;\n const nodeById = new Map(dataset.nodes.map((n) => [n.id, n] as const));\n const out: ValveCandidate[] = [];\n const endpoint = startId === pipe.fromNode ? 'from' : 'to';\n\n const startNode = nodeById.get(startId);\n if (!startNode) return [];\n\n // 0) 端点本身就是阀门 → 立即返回\n if (startNode.kind === 'valve') {\n if (!skipClosed || startNode.properties?.valveStatus !== 'closed') {\n out.push({ node: startNode, hops: 0, distance: 0, endpoint });\n }\n return out;\n }\n\n // 1) 否则 BFS 找最近的阀门\n const visited = new Set<string>();\n const queue: Array<{ id: string; hops: number; dist: number }> = [\n { id: startId, hops: 0, dist: 0 },\n ];\n\n while (queue.length > 0) {\n const cur = queue.shift()!;\n if (visited.has(cur.id)) continue;\n visited.add(cur.id);\n\n const n = nodeById.get(cur.id);\n if (!n) continue;\n\n if (n.kind === 'valve' && (!skipClosed || n.properties?.valveStatus !== 'closed')) {\n out.push({ node: n, hops: cur.hops, distance: cur.dist, endpoint });\n return out; // 找最近的,返回\n }\n\n const edges = adj.get(cur.id) ?? [];\n for (const e of edges) {\n if (e.pipeId === faultPipeId) continue;\n if (visited.has(e.to)) continue;\n queue.push({\n id: e.to,\n hops: cur.hops + 1,\n dist: cur.dist + (e.length || 0),\n });\n }\n }\n\n return out;\n}\n\n/** 合并上下游阀门候选(按距离排重) */\nfunction mergeCandidateValves(\n upstream: ValveCandidate[],\n downstream: ValveCandidate[]\n): PipelineNode[] {\n const seen = new Set<string>();\n const all = [...upstream, ...downstream].sort((a, b) => a.distance - b.distance);\n const out: PipelineNode[] = [];\n for (const c of all) {\n if (seen.has(c.node.id)) continue;\n seen.add(c.node.id);\n out.push(c.node);\n }\n return out;\n}\n\n/**\n * 构造影响区域\n * - features: 受影响节点(Point) + 受影响管段(LineString)\n * - hull: 节点集的凸包(用于地图高亮\"受影响地理范围\")\n */\nfunction computeImpactArea(\n nodes: PipelineNode[],\n pipes: PipelinePipe[]\n): ImpactArea {\n const features: ImpactArea['features'] = [];\n const nodeById = new Map(nodes.map((n) => [n.id, n] as const));\n\n for (const n of nodes) {\n features.push({\n type: 'Feature',\n geometry: { type: 'Point', coordinates: [n.lng, n.lat] },\n properties: { kind: 'node' },\n });\n }\n for (const p of pipes) {\n let coords: [number, number][] = [];\n if (p.geometry && p.geometry.length >= 2) {\n coords = p.geometry as [number, number][];\n } else {\n const from = nodeById.get(p.fromNode);\n const to = nodeById.get(p.toNode);\n if (from && to) coords = [[from.lng, from.lat], [to.lng, to.lat]];\n }\n if (coords.length >= 2) {\n features.push({\n type: 'Feature',\n geometry: { type: 'LineString', coordinates: coords },\n properties: { kind: 'pipe' },\n });\n }\n }\n\n const hull = convexHull(nodes.map((n) => [n.lng, n.lat] as [number, number]));\n\n return { type: 'FeatureCollection', features, hull };\n}\n\n/**\n * 构造阀门隔离方案\n */\nfunction buildValvePlan(\n adj: AdjacencyList,\n dataset: PipelineTopologyDataset,\n pipe: PipelinePipe,\n closeValves: PipelineNode[],\n _affectedNodes: PipelineNode[],\n maxAlt: number,\n scenario: string\n): ValvePlan {\n const closeSet = new Set(closeValves.map((v) => v.id));\n\n // 找泄压点:受影响区域内\"开放\"且\"不在关闭列表\"的阀门\n const openValves: PipelineNode[] = [];\n for (const n of _affectedNodes) {\n if (n.kind !== 'valve') continue;\n if (closeSet.has(n.id)) continue;\n if (n.properties?.valveStatus !== 'open') continue;\n const from = dataset.nodes.find((m) => m.id === pipe.fromNode);\n const to = dataset.nodes.find((m) => m.id === pipe.toNode);\n if (!from || !to) continue;\n const d1 = haversine(n.lng, n.lat, from.lng, from.lat);\n const d2 = haversine(n.lng, n.lat, to.lng, to.lat);\n if (Math.min(d1, d2) < 1000) openValves.push(n);\n }\n\n // 备选路径:从关闭阀门出发 → 其它 source(隔离后备用气源/水源)\n const alternativePaths: string[][] = [];\n if (closeValves.length) {\n const sources = dataset.nodes.filter((n) => n.kind === 'source');\n for (const s of sources) {\n // 选最接近关闭阀门的 source 寻路(确保目标非 closed 阀门)\n const r = dijkstra(adj, closeValves[0].id, s.id, {\n weight: (e) => (closeSet.has(e.to) ? Infinity : e.length || 1),\n });\n if (r.found) {\n const paths = findPaths(adj, closeValves[0].id, s.id, {\n maxPaths: maxAlt,\n maxDepth: 20,\n });\n for (const p of paths) alternativePaths.push(p);\n break;\n }\n }\n }\n\n // 估算停气/停水时间(基于受影响用户数和场景)\n const userCount = (dataset.users ?? []).filter((u) =>\n _affectedNodes.some((n) => n.id === u.nodeId)\n ).length;\n const baseHours = userCount / 200;\n const scenarioFactor = scenario === 'water' ? 1.5 : scenario === 'heating' ? 2 : 1;\n const hours = Math.max(0.5, Math.min(8, baseHours * scenarioFactor));\n const estimatedShutdownTime = hours >= 1 ? `${hours.toFixed(1)}h` : `${Math.round(hours * 60)}min`;\n\n const summary = buildSummary(closeValves, openValves, userCount, scenario);\n\n return {\n closeValves,\n openValves,\n alternativePaths,\n estimatedShutdownTime,\n summary,\n };\n}\n\nfunction buildSummary(\n closeValves: PipelineNode[],\n openValves: PipelineNode[],\n userCount: number,\n scenario: string\n): string {\n const labels: Record<string, string> = {\n gas: '停气',\n water: '停水',\n drainage: '排水中断',\n heating: '停热',\n };\n const label = labels[scenario] ?? '受影响';\n const parts: string[] = [];\n parts.push(`预计${label}${userCount}户`);\n if (closeValves.length) {\n parts.push(`关闭阀门 ${closeValves.map((v) => v.properties?.code ?? v.id).join(', ')}`);\n } else {\n parts.push('未找到上游隔离阀门(建议人工指定)');\n }\n if (openValves.length) {\n parts.push(`打开阀门 ${openValves.map((v) => v.properties?.code ?? v.id).join(', ')}(泄压)`);\n }\n return parts.join(';');\n}\n\n// ============================================================\n// 凸包(Andrew's monotone chain,O(n log n))\n// ============================================================\n\n/** Andrew's monotone chain,返回逆时针凸包顶点(首尾不重复) */\nexport function convexHull(points: [number, number][]): [number, number][] {\n if (points.length < 3) return [...points];\n const pts = [...points];\n pts.sort((a, b) => (a[0] - b[0]) || (a[1] - b[1]));\n\n const cross = (\n o: [number, number],\n a: [number, number],\n b: [number, number]\n ): number => (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]);\n\n const lower: [number, number][] = [];\n for (const p of pts) {\n while (lower.length >= 2 && cross(lower[lower.length - 2], lower[lower.length - 1], p) <= 0) {\n lower.pop();\n }\n lower.push(p);\n }\n const upper: [number, number][] = [];\n for (let i = pts.length - 1; i >= 0; i--) {\n const p = pts[i];\n while (upper.length >= 2 && cross(upper[upper.length - 2], upper[upper.length - 1], p) <= 0) {\n upper.pop();\n }\n upper.push(p);\n }\n upper.pop();\n lower.pop();\n return lower.concat(upper);\n}\n\n/** 用户严重程度打分(用于\"优先通告\"列表) */\nexport function userSeverity(kind: UserKind, scale = 1): number {\n const base: Record<UserKind, number> = {\n important: 100,\n industrial: 50,\n commercial: 20,\n residential: 1,\n };\n return (base[kind] ?? 1) * (scale ?? 1);\n}\n","/**\n * 阀门规划(valve planner)\n *\n * 在已知故障管段的前提下,候选出最优的\"关闭+打开\"组合。\n * 评估指标:\n * - 隔离完整性:关闭阀门后故障段必须与气源/水源完全分离\n * - 影响最小:关闭数量最小,受影响用户最少\n * - 操作便利:按操作顺序列出阀门编号\n */\n\nimport type { PipelineNode, PipelineTopologyDataset, PipelinePipe } from '../types';\nimport { buildAdjacency, type AdjacencyList } from '../graph/adjacency';\nimport { bfs } from '../graph/bfs';\nimport { dijkstra } from '../graph/shortestPath';\n\nexport interface CandidateValveSet {\n valves: PipelineNode[];\n /** 完整性:关闭后故障段到最近 source 的最短距离(Infinity = 完全隔离) */\n isolationCompleteness: number;\n /** 受影响用户数(关闭阀门后的下游覆盖) */\n impactUserCount: number;\n /** 阀门操作顺序(按节点编号字典序,仅辅助) */\n operationOrder: string[];\n}\n\nexport interface PlannerOptions {\n /** 最大候选组合数(指数爆炸时截断) */\n maxCombinations?: number;\n /** 阀门过滤:仅考虑状态/类型匹配的 */\n filter?: (valve: PipelineNode) => boolean;\n}\n\n/**\n * 列出上游候选阀门(沿故障 pipe 两端 BFS 找到的所有阀门,按距离排序)\n */\nexport function listCandidateValves(\n dataset: PipelineTopologyDataset,\n pipeId: string,\n filter?: (valve: PipelineNode) => boolean\n): PipelineNode[] {\n const pipe = dataset.pipes.find((p) => p.id === pipeId);\n if (!pipe) return [];\n const nodeById = new Map(dataset.nodes.map((n) => [n.id, n] as const));\n const adj = buildAdjacency(dataset);\n\n const visited = new Set<string>();\n const valveCandidates: Array<{ n: PipelineNode; dist: number }> = [];\n\n for (const startId of [pipe.fromNode, pipe.toNode]) {\n const queue: Array<{ id: string; d: number }> = [{ id: startId, d: 0 }];\n while (queue.length > 0) {\n const { id, d } = queue.shift()!;\n if (visited.has(id)) continue;\n visited.add(id);\n\n const n = nodeById.get(id);\n if (!n) continue;\n // 端点本身如果是阀门, 也算候选\n if (n.kind === 'valve' && (!filter || filter(n))) {\n valveCandidates.push({ n, dist: d });\n // 第一个阀门已找到, 不必继续扩展 (但允许从端点继续找其它)\n if (d > 0) continue;\n }\n\n const edges = adj.get(id) ?? [];\n for (const e of edges) {\n if (e.pipeId === pipeId) continue; // 不穿过故障 pipe\n if (visited.has(e.to)) continue;\n queue.push({ id: e.to, d: d + 1 });\n }\n }\n }\n\n valveCandidates.sort((a, b) => a.dist - b.dist);\n return valveCandidates.map((v) => v.n);\n}\n\n/**\n * 评估某组阀门关闭后的隔离完整性与受影响用户数\n */\nexport function evaluateValvePlan(\n dataset: PipelineTopologyDataset,\n pipeId: string,\n valvesToClose: PipelineNode[]\n): CandidateValveSet {\n const pipe = dataset.pipes.find((p) => p.id === pipeId);\n if (!pipe) {\n return {\n valves: valvesToClose,\n isolationCompleteness: Infinity,\n impactUserCount: 0,\n operationOrder: [],\n };\n }\n\n // 模拟\"关闭阀门 = 在邻接表中标记为不可通过\",重新计算下游覆盖\n const adj = buildAdjacency(dataset);\n const closedSet = new Set(valvesToClose.map((v) => v.id));\n const pipeById = new Map(dataset.pipes.map((p) => [p.id, p] as const));\n\n const affectedNodes = bfs(adj, pipe.toNode, {\n allowEdge: (_e, _f, to) => !closedSet.has(to),\n maxDepth: 1000,\n }).visited;\n\n // 受影响用户数\n const users = (dataset.users ?? []).filter((u) => {\n if (!u.nodeId) return false;\n return affectedNodes.includes(u.nodeId);\n });\n\n // 隔离完整性:source → 故障段 任一端 的可达性\n// 语义:所有 source 都不能绕过 closedSet 抵达 fromNode/toNode → Infinity(完全隔离)\n// 否则:completeness = source 到故障段最近的可达距离(米)\n const sources = dataset.nodes.filter((n) => n.kind === 'source');\n let completeness = Infinity;\n for (const s of sources) {\n const rTo = dijkstra(adj, s.id, pipe.toNode, {\n weight: (e) => (closedSet.has(e.to) ? Infinity : e.length || 1),\n });\n const rFrom = dijkstra(adj, s.id, pipe.fromNode, {\n weight: (e) => (closedSet.has(e.to) ? Infinity : e.length || 1),\n });\n const reachable =\n rTo.found ? rTo.distance : Infinity;\n const reachableFrom =\n rFrom.found ? rFrom.distance : Infinity;\n const nearest = Math.min(reachable, reachableFrom);\n if (nearest < completeness) completeness = nearest;\n }\n\n const order = valvesToClose\n .map((v) => v.properties?.code ?? v.id)\n .sort();\n\n return {\n valves: valvesToClose,\n isolationCompleteness: completeness,\n impactUserCount: users.length,\n operationOrder: order,\n };\n}\n","/**\n * 影响区域 helpers\n *\n * 把 BurstSimulator 输出的受影响节点+管段渲染成 MapLibre 图层用的 GeoJSON。\n */\n\nimport type { BurstSimulateResult } from './burstCore';\nimport type { PipelineNode, PipelinePipe } from '../types';\n\nexport interface MapLayerData {\n /** 受影响区域凸包多边形(用于高亮) */\n hullPolygon: GeoJSON.Feature<\n GeoJSON.Polygon,\n { score: number; affected: number }\n > | null;\n /** 受影响管段 LineString 集合(用于粗化红色线) */\n affectedPipes: GeoJSON.FeatureCollection<\n GeoJSON.LineString,\n { pipeId: string; scenario: string }\n >;\n /** 受影响节点 Point 集合 */\n affectedNodes: GeoJSON.FeatureCollection<\n GeoJSON.Point,\n { nodeId: string; kind: string }\n >;\n}\n\n/**\n * 把 BurstSimulateResult 映射为地图图层数据\n */\nexport function toMapLayerData(result: BurstSimulateResult): MapLayerData {\n const hull = result.impactArea.hull;\n const hullPolygon: MapLayerData['hullPolygon'] = hull.length >= 3\n ? {\n type: 'Feature',\n geometry: { type: 'Polygon', coordinates: [hull] },\n properties: { score: 1, affected: result.affectedUserCount },\n }\n : null;\n\n // 构造 node 坐标索引以便退化几何\n const nodeCoords = new Map<string, { lng: number; lat: number }>();\n for (const n of result.affectedNodes) nodeCoords.set(n.id, n);\n\n const affectedPipes: GeoJSON.FeatureCollection<GeoJSON.LineString, { pipeId: string; scenario: string }> = {\n type: 'FeatureCollection',\n features: result.affectedPipes\n .map((p) => ({\n type: 'Feature' as const,\n geometry: pipeToLineString(p, nodeCoords),\n properties: { pipeId: p.id, scenario: 'affected' },\n }))\n .filter((f) => f.geometry.coordinates.length >= 2),\n };\n\n const affectedNodes: GeoJSON.FeatureCollection<GeoJSON.Point, { nodeId: string; kind: string }> = {\n type: 'FeatureCollection',\n features: result.affectedNodes.map((n) => ({\n type: 'Feature' as const,\n geometry: { type: 'Point', coordinates: [n.lng, n.lat] },\n properties: { nodeId: n.id, kind: n.kind },\n })),\n };\n\n return { hullPolygon, affectedPipes, affectedNodes };\n}\n\nfunction pipeToLineString(p: PipelinePipe, nodes: Map<string, { lng: number; lat: number }>): GeoJSON.LineString {\n if (p.geometry && p.geometry.length >= 2) {\n return { type: 'LineString', coordinates: p.geometry as [number, number][] };\n }\n // 退化:从端点拉直线\n const from = nodes.get(p.fromNode);\n const to = nodes.get(p.toNode);\n if (from && to) {\n return {\n type: 'LineString',\n coordinates: [\n [from.lng, from.lat],\n [to.lng, to.lat],\n ],\n };\n }\n return { type: 'LineString', coordinates: [] };\n}\n\n/** 计算受影响区域总面积(使用 shoelace 公式) */\nexport function impactAreaSquareMeters(hull: [number, number][]): number {\n if (hull.length < 3) return 0;\n // 把经纬度局部转米(以第一个点为原点,使用等距近似)\n const refLat = hull[0][1];\n const mPerDegLat = 110_540;\n const mPerDegLng = 111_320 * Math.cos((refLat * Math.PI) / 180);\n\n const pts = hull.map(([lng, lat]) => [\n (lng - hull[0][0]) * mPerDegLng,\n (lat - hull[0][1]) * mPerDegLat,\n ]);\n\n let sum = 0;\n for (let i = 0; i < pts.length; i++) {\n const [x1, y1] = pts[i];\n const [x2, y2] = pts[(i + 1) % pts.length];\n sum += x1 * y2 - x2 * y1;\n }\n return Math.abs(sum) / 2;\n}\n\n/** 估算受影响节点的\"中心点\"(用于地图 flyTo) */\nexport function impactCenter(nodes: PipelineNode[]): [number, number] | null {\n if (!nodes.length) return null;\n let lng = 0;\n let lat = 0;\n for (const n of nodes) {\n lng += n.lng;\n lat += n.lat;\n }\n return [lng / nodes.length, lat / nodes.length];\n}\n\n/** 从管段上取最近的节点(用于点击管线后弹出该节点信息卡) */\nexport function nearestNodeOnPipe(\n pipe: PipelinePipe,\n nodes: PipelineNode[],\n lng: number,\n lat: number\n): PipelineNode | null {\n const a = nodes.find((n) => n.id === pipe.fromNode);\n const b = nodes.find((n) => n.id === pipe.toNode);\n if (!a || !b) return null;\n const da = haversineApprox(a.lng, a.lat, lng, lat);\n const db = haversineApprox(b.lng, b.lat, lng, lat);\n return da < db ? a : b;\n}\n\nfunction haversineApprox(lng1: number, lat1: number, lng2: number, lat2: number): number {\n const dx = (lng2 - lng1) * 111_320 * Math.cos((lat1 * Math.PI) / 180);\n const dy = (lat2 - lat1) * 110_540;\n return Math.sqrt(dx * dx + dy * dy);\n}\n","/**\n * BurstSimulator 组件类(地图集成层)\n *\n * 包装 simulateBurst 纯函数 + 维护 MapLibre 图层状态。\n * 组件层职责:\n * - 接收地图实例,添加受影响区域/管段/阀门、方案侧栏\n * - 暴露 simulate()、clear() 等命令式 API\n * - 可订阅结果事件(affectedNodes/valvePlan/impactArea)\n *\n * 注意:此组件不直接依赖 Vue/React(业务方可在任意框架中实例化)\n */\n\nimport type { Map as CaoguoMap } from '@caoguo/maplibre';\nimport {\n simulateBurst,\n type BurstSimulateOptions,\n type BurstSimulateResult,\n} from './burstCore';\nimport { toMapLayerData } from './impactArea';\nimport type { PipelineTopologyDataset, PipelineType } from '../types';\n\nexport interface BurstSimulatorOptions {\n map: CaoguoMap;\n dataset: PipelineTopologyDataset;\n /** 受影响管段样式(maplibre paint props) */\n affectedPipePaint?: Record<string, unknown>;\n /** 阀门隔离方案样式 */\n valvePaint?: Record<string, unknown>;\n /** 影响区域凸包样式 */\n hullPaint?: Record<string, unknown>;\n /** 受影响节点图标样式 */\n affectedNodePaint?: Record<string, unknown>;\n /** 推演情景 */\n scenario?: BurstSimulateOptions['scenario'];\n /** 该实例只处理指定管线类型(用于多管类地图) */\n pipelineType?: PipelineType;\n /** 层 ID 前缀(避免多实例冲突) */\n layerPrefix?: string;\n}\n\nexport type BurstResult = BurstSimulateResult;\n\ntype Listener = (r: BurstSimulateResult) => void;\n\n/**\n * 爆管推演组件(前端类)\n *\n * 用法:\n * const sim = new BurstSimulator({ map, dataset });\n * const result = sim.simulate('pipe-A12');\n * // 受影响区域已添加到 map\n * sim.clear();\n * sim.destroy();\n */\nexport class BurstSimulator {\n private map: CaoguoMap;\n private dataset: PipelineTopologyDataset;\n private scenario: 'gas' | 'water' | 'drainage' | 'heating';\n private affectedPipePaint: Record<string, unknown>;\n private affectedNodePaint: Record<string, unknown>;\n private valvePaint: Record<string, unknown>;\n private hullPaint: Record<string, unknown>;\n private layerPrefix: string;\n private listeners = new Set<Listener>();\n private lastResult: BurstSimulateResult | null = null;\n private layerIds: string[] = [];\n\n constructor(options: BurstSimulatorOptions) {\n this.map = options.map;\n this.dataset = options.dataset;\n this.scenario = options.scenario ?? 'gas';\n this.affectedPipePaint = options.affectedPipePaint ?? {\n 'line-color': '#ef4444',\n 'line-width': 4,\n 'line-opacity': 0.85,\n 'line-blur': 1.5,\n };\n this.affectedNodePaint = options.affectedNodePaint ?? {\n 'circle-radius': 6,\n 'circle-color': '#ef4444',\n 'circle-stroke-width': 2,\n 'circle-stroke-color': '#ffffff',\n };\n this.valvePaint = options.valvePaint ?? {\n 'circle-radius': 8,\n 'circle-color': '#fbbf24',\n 'circle-stroke-width': 2,\n 'circle-stroke-color': '#000000',\n };\n this.hullPaint = options.hullPaint ?? {\n 'fill-color': '#ef4444',\n 'fill-opacity': 0.15,\n 'fill-outline-color': '#ef4444',\n };\n this.layerPrefix = options.layerPrefix ?? 'cg-burst';\n }\n\n /** 触发爆管推演 */\n simulate(pipeId: string, overrideOpts?: BurstSimulateOptions): BurstSimulateResult {\n const result = simulateBurst(this.dataset, pipeId, {\n scenario: overrideOpts?.scenario ?? this.scenario,\n skipClosedValves: overrideOpts?.skipClosedValves ?? true,\n maxAlternatives: overrideOpts?.maxAlternatives ?? 2,\n });\n this.lastResult = result;\n this.render(result);\n for (const l of this.listeners) l(result);\n return result;\n }\n\n /** 清空所有受影响区域图层 */\n clear(): void {\n for (const id of this.layerIds) {\n this.map.removeLayer(id);\n }\n this.layerIds = [];\n }\n\n /** 销毁并清空所有资源 */\n destroy(): void {\n this.clear();\n this.listeners.clear();\n this.lastResult = null;\n }\n\n /** 订阅推演结果 */\n onResult(fn: Listener): () => void {\n this.listeners.add(fn);\n return () => this.listeners.delete(fn);\n }\n\n /** 取最后一次结果 */\n getLastResult(): BurstSimulateResult | null {\n return this.lastResult;\n }\n\n // ------------------------------------------------------\n // 内部:把结果渲染为 MapLibre 图层\n // ------------------------------------------------------\n private render(result: BurstSimulateResult): void {\n this.clear();\n const layerData = toMapLayerData(result);\n const mlMap = (this.map as unknown as {\n instance: {\n addSource: (id: string, source: unknown) => void;\n addLayer: (layer: unknown) => void;\n getSource: (id: string) => unknown;\n };\n }).instance;\n\n const prefix = this.layerPrefix;\n const sourcesToAdd: Array<{ id: string; data: unknown }> = [];\n const layersToAdd: Array<Record<string, unknown>> = [];\n\n if (layerData.hullPolygon) {\n sourcesToAdd.push({ id: `${prefix}-hull-src`, data: layerData.hullPolygon });\n layersToAdd.push({\n id: `${prefix}-hull-fill`,\n type: 'fill',\n source: `${prefix}-hull-src`,\n paint: this.hullPaint,\n });\n }\n\n sourcesToAdd.push({ id: `${prefix}-pipes-src`, data: layerData.affectedPipes });\n layersToAdd.push({\n id: `${prefix}-pipes-line`,\n type: 'line',\n source: `${prefix}-pipes-src`,\n paint: this.affectedPipePaint,\n });\n\n sourcesToAdd.push({ id: `${prefix}-nodes-src`, data: layerData.affectedNodes });\n layersToAdd.push({\n id: `${prefix}-nodes-pt`,\n type: 'circle',\n source: `${prefix}-nodes-src`,\n paint: this.affectedNodePaint,\n });\n\n for (const src of sourcesToAdd) {\n if (!mlMap.getSource(src.id)) mlMap.addSource(src.id, src.data as never);\n }\n for (const layer of layersToAdd) {\n try {\n mlMap.addLayer(layer);\n this.layerIds.push(layer.id as string);\n } catch {\n // ignore duplicate\n }\n }\n }\n}\n"]}
|
package/dist/burst/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { BurstSimulator, convexHull, evaluateValvePlan, impactAreaSquareMeters, impactCenter, listCandidateValves, nearestNodeOnPipe, simulateBurst, toMapLayerData, userSeverity } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
1
|
+
export { BurstSimulator, convexHull, evaluateValvePlan, impactAreaSquareMeters, impactCenter, listCandidateValves, nearestNodeOnPipe, simulateBurst, toMapLayerData, userSeverity } from '../chunk-2O4IXAXO.js';
|
|
2
|
+
import '../chunk-XCP7XVNO.js';
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { buildAdjacency, bfs, haversine, dijkstra, findPaths } from './chunk-
|
|
1
|
+
import { buildAdjacency, bfs, haversine, dijkstra, findPaths } from './chunk-XCP7XVNO.js';
|
|
2
2
|
|
|
3
3
|
// src/burst/burstCore.ts
|
|
4
4
|
function simulateBurst(dataset, pipeId, opts = {}) {
|
|
@@ -528,5 +528,5 @@ var BurstSimulator = class {
|
|
|
528
528
|
};
|
|
529
529
|
|
|
530
530
|
export { BurstSimulator, convexHull, evaluateValvePlan, impactAreaSquareMeters, impactCenter, listCandidateValves, nearestNodeOnPipe, simulateBurst, toMapLayerData, userSeverity };
|
|
531
|
-
//# sourceMappingURL=chunk-
|
|
532
|
-
//# sourceMappingURL=chunk-
|
|
531
|
+
//# sourceMappingURL=chunk-2O4IXAXO.js.map
|
|
532
|
+
//# sourceMappingURL=chunk-2O4IXAXO.js.map
|