@caoguo/maplibre-pipeline 0.0.1
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/dist/burst/index.cjs +708 -0
- package/dist/burst/index.cjs.map +1 -0
- package/dist/burst/index.d.cts +74 -0
- package/dist/burst/index.d.ts +74 -0
- package/dist/burst/index.js +4 -0
- package/dist/burst/index.js.map +1 -0
- package/dist/burstClass-CGMjcAYy.d.cts +161 -0
- package/dist/burstClass-Cf2p71LE.d.ts +161 -0
- package/dist/chunk-CDEYJ67B.js +80 -0
- package/dist/chunk-CDEYJ67B.js.map +1 -0
- package/dist/chunk-GCDA7KJM.js +289 -0
- package/dist/chunk-GCDA7KJM.js.map +1 -0
- package/dist/chunk-GEJRE2OR.js +351 -0
- package/dist/chunk-GEJRE2OR.js.map +1 -0
- package/dist/chunk-HCT6NSNS.js +532 -0
- package/dist/chunk-HCT6NSNS.js.map +1 -0
- package/dist/chunk-HIRNJVCV.js +13 -0
- package/dist/chunk-HIRNJVCV.js.map +1 -0
- package/dist/chunk-J3AEVXT4.js +164 -0
- package/dist/chunk-J3AEVXT4.js.map +1 -0
- package/dist/chunk-QVY4WJLM.js +256 -0
- package/dist/chunk-QVY4WJLM.js.map +1 -0
- package/dist/chunk-VA2TQWL3.js +340 -0
- package/dist/chunk-VA2TQWL3.js.map +1 -0
- package/dist/chunk-YBLESEN4.js +133 -0
- package/dist/chunk-YBLESEN4.js.map +1 -0
- package/dist/chunk-YS2ICFVK.js +101 -0
- package/dist/chunk-YS2ICFVK.js.map +1 -0
- package/dist/graph/index.cjs +382 -0
- package/dist/graph/index.cjs.map +1 -0
- package/dist/graph/index.d.cts +211 -0
- package/dist/graph/index.d.ts +211 -0
- package/dist/graph/index.js +4 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/health/index.cjs +348 -0
- package/dist/health/index.cjs.map +1 -0
- package/dist/health/index.d.cts +210 -0
- package/dist/health/index.d.ts +210 -0
- package/dist/health/index.js +3 -0
- package/dist/health/index.js.map +1 -0
- package/dist/index.cjs +2295 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/leakage/index.cjs +358 -0
- package/dist/leakage/index.cjs.map +1 -0
- package/dist/leakage/index.d.cts +212 -0
- package/dist/leakage/index.d.ts +212 -0
- package/dist/leakage/index.js +3 -0
- package/dist/leakage/index.js.map +1 -0
- package/dist/nlpg/index.cjs +136 -0
- package/dist/nlpg/index.cjs.map +1 -0
- package/dist/nlpg/index.d.cts +51 -0
- package/dist/nlpg/index.d.ts +51 -0
- package/dist/nlpg/index.js +3 -0
- package/dist/nlpg/index.js.map +1 -0
- package/dist/style/index.cjs +379 -0
- package/dist/style/index.cjs.map +1 -0
- package/dist/style/index.d.cts +119 -0
- package/dist/style/index.d.ts +119 -0
- package/dist/style/index.js +4 -0
- package/dist/style/index.js.map +1 -0
- package/dist/topology/index.cjs +317 -0
- package/dist/topology/index.cjs.map +1 -0
- package/dist/topology/index.d.cts +69 -0
- package/dist/topology/index.d.ts +69 -0
- package/dist/topology/index.js +4 -0
- package/dist/topology/index.js.map +1 -0
- package/dist/types/index.cjs +15 -0
- package/dist/types/index.cjs.map +1 -0
- package/dist/types/index.d.cts +214 -0
- package/dist/types/index.d.ts +214 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +81 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/leakage/pasquillGifford.ts
|
|
4
|
+
var TABLE_DAY = [
|
|
5
|
+
{ wind: 2, cls: { strong: "A", moderate: "A", slight: "B" } },
|
|
6
|
+
{ wind: 3, cls: { strong: "A", moderate: "B", slight: "C" } },
|
|
7
|
+
{ wind: 5, cls: { strong: "B", moderate: "B", slight: "C" } },
|
|
8
|
+
{ wind: 6, cls: { strong: "C", moderate: "C", slight: "D" } },
|
|
9
|
+
{ wind: 7, cls: { strong: "C", moderate: "D", slight: "D" } },
|
|
10
|
+
{ wind: 999, cls: { strong: "D", moderate: "D", slight: "D" } }
|
|
11
|
+
];
|
|
12
|
+
var TABLE_NIGHT = [
|
|
13
|
+
{ wind: 2, cls: { overcast: "F", partly: "F", clear: "F" } },
|
|
14
|
+
{ wind: 3, cls: { overcast: "E", partly: "F", clear: "F" } },
|
|
15
|
+
{ wind: 5, cls: { overcast: "D", partly: "E", clear: "F" } },
|
|
16
|
+
{ wind: 6, cls: { overcast: "D", partly: "D", clear: "E" } },
|
|
17
|
+
{ wind: 999, cls: { overcast: "D", partly: "D", clear: "D" } }
|
|
18
|
+
];
|
|
19
|
+
function classifyStability(params) {
|
|
20
|
+
const table = params.isDaytime ? TABLE_DAY : TABLE_NIGHT;
|
|
21
|
+
const key = params.isDaytime ? params.daytimeInsolation ?? "moderate" : params.nightCloudCover ?? "partly";
|
|
22
|
+
for (const row of table) {
|
|
23
|
+
if (params.windSpeed < row.wind) return row.cls[key] ?? "D";
|
|
24
|
+
}
|
|
25
|
+
return "D";
|
|
26
|
+
}
|
|
27
|
+
function dispersionCoefficients(stability) {
|
|
28
|
+
const params = {
|
|
29
|
+
A: [0.22, 1e-4, 0.2, 0],
|
|
30
|
+
B: [0.16, 1e-4, 0.12, 0],
|
|
31
|
+
C: [0.11, 1e-4, 0.08, 2e-4],
|
|
32
|
+
D: [0.08, 1e-4, 0.06, 15e-4],
|
|
33
|
+
E: [0.06, 1e-4, 0.03, 3e-4],
|
|
34
|
+
F: [0.04, 1e-4, 0.016, 3e-4]
|
|
35
|
+
};
|
|
36
|
+
const [a, b, c, d] = params[stability];
|
|
37
|
+
return {
|
|
38
|
+
sigmaY: (xMeters) => {
|
|
39
|
+
const xKm = xMeters / 1e3;
|
|
40
|
+
return a * xKm / Math.sqrt(1 + b * xKm) * 1e3;
|
|
41
|
+
},
|
|
42
|
+
sigmaZ: (xMeters) => {
|
|
43
|
+
const xKm = xMeters / 1e3;
|
|
44
|
+
return c * xKm / Math.sqrt(1 + d * xKm) * 1e3;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// src/leakage/gaussianPlume.ts
|
|
50
|
+
function gaussianPlume(source, params) {
|
|
51
|
+
const stability = params.stability ?? "D";
|
|
52
|
+
const { sigmaY, sigmaZ } = dispersionCoefficients(stability);
|
|
53
|
+
const thresholds = params.thresholds ?? [1e-3, 5e-3, 0.01];
|
|
54
|
+
const step = params.gridStep ?? 50;
|
|
55
|
+
const range = params.range ?? 5e3;
|
|
56
|
+
const contourList = thresholds.map((t) => ({
|
|
57
|
+
threshold: t,
|
|
58
|
+
polygon: [],
|
|
59
|
+
closed: false
|
|
60
|
+
}));
|
|
61
|
+
const Q = params.leakRate;
|
|
62
|
+
const u = params.windSpeed;
|
|
63
|
+
const H = params.releaseHeight;
|
|
64
|
+
let maxDownwindDistance = 0;
|
|
65
|
+
for (const c of contourList) {
|
|
66
|
+
for (let r = step; r <= range; r += step) {
|
|
67
|
+
const sy = sigmaY(r);
|
|
68
|
+
const sz = sigmaZ(r);
|
|
69
|
+
if (sy <= 0 || sz <= 0) continue;
|
|
70
|
+
const concCenter = Q / (2 * Math.PI * sy * sz * u);
|
|
71
|
+
const zTerm = 2 * Math.exp(-(H * H) / (2 * sz * sz));
|
|
72
|
+
const cMax = concCenter * zTerm;
|
|
73
|
+
if (cMax >= c.threshold) {
|
|
74
|
+
if (r > maxDownwindDistance) maxDownwindDistance = r;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const poly = [];
|
|
78
|
+
for (let r = step; r <= range; r += step) {
|
|
79
|
+
const sy = sigmaY(r);
|
|
80
|
+
if (sy <= 0) continue;
|
|
81
|
+
const syy = Q / (2 * Math.PI * sy * sigmaZ(r) * u) * 2;
|
|
82
|
+
if (syy < c.threshold) continue;
|
|
83
|
+
const ratio = c.threshold * Math.PI * sy * sigmaZ(r) * u / Q;
|
|
84
|
+
if (ratio >= 1) continue;
|
|
85
|
+
const yMax = sy * Math.sqrt(-2 * Math.log(ratio));
|
|
86
|
+
poly.push([r, yMax]);
|
|
87
|
+
poly.unshift([r, -yMax]);
|
|
88
|
+
}
|
|
89
|
+
c.polygon = polyToLngLat(source, params.windDirection, poly);
|
|
90
|
+
c.closed = poly.length >= 3;
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
source,
|
|
94
|
+
windDirection: params.windDirection,
|
|
95
|
+
windSpeed: params.windSpeed,
|
|
96
|
+
stability,
|
|
97
|
+
contours: contourList,
|
|
98
|
+
maxDownwindDistance
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function polyToLngLat(source, windDir, poly) {
|
|
102
|
+
return poly.map(([r, y]) => {
|
|
103
|
+
const cosW = Math.cos(windDir);
|
|
104
|
+
const sinW = Math.sin(windDir);
|
|
105
|
+
const dx = r * cosW + y * -sinW;
|
|
106
|
+
const dy = r * sinW + y * cosW;
|
|
107
|
+
const dLat = dy / 110540;
|
|
108
|
+
const dLng = dx / (111320 * Math.cos(source.lat * Math.PI / 180));
|
|
109
|
+
return [source.lng + dLng, source.lat + dLat];
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
function classifyFromMeteo(opts) {
|
|
113
|
+
return classifyStability(opts);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// src/leakage/floodFill.ts
|
|
117
|
+
function simulateFlood(dem, params) {
|
|
118
|
+
const sourceIdx = lngLatToIndex(dem, params.sourceLng, params.sourceLat);
|
|
119
|
+
if (sourceIdx.row < 0 || sourceIdx.row >= dem.rows || sourceIdx.col < 0 || sourceIdx.col >= dem.cols) {
|
|
120
|
+
return {
|
|
121
|
+
source: { lng: params.sourceLng, lat: params.sourceLat },
|
|
122
|
+
floodArea: 0,
|
|
123
|
+
affectedCells: [],
|
|
124
|
+
hull: [],
|
|
125
|
+
maxDepth: 0
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
const sourceElev = dem.elevations[sourceIdx.row * dem.cols + sourceIdx.col] ?? 0;
|
|
129
|
+
(params.duration ?? 30 * 60) / 60;
|
|
130
|
+
params.flowRate ?? 50;
|
|
131
|
+
const initialLevel = params.initialWaterLevel ?? sourceElev + 0.05;
|
|
132
|
+
const visited = /* @__PURE__ */ new Set();
|
|
133
|
+
const affected = [];
|
|
134
|
+
const queue = [];
|
|
135
|
+
queue.push({ row: sourceIdx.row, col: sourceIdx.col, level: initialLevel });
|
|
136
|
+
let maxDepth = 0;
|
|
137
|
+
while (queue.length > 0) {
|
|
138
|
+
const cur = queue.shift();
|
|
139
|
+
const idx = cur.row * dem.cols + cur.col;
|
|
140
|
+
if (visited.has(idx)) continue;
|
|
141
|
+
visited.add(idx);
|
|
142
|
+
if (cur.row < 0 || cur.row >= dem.rows) continue;
|
|
143
|
+
if (cur.col < 0 || cur.col >= dem.cols) continue;
|
|
144
|
+
const elev = dem.elevations[idx] ?? 0;
|
|
145
|
+
const depth = cur.level - elev;
|
|
146
|
+
if (depth <= 0) continue;
|
|
147
|
+
if (depth > maxDepth) maxDepth = depth;
|
|
148
|
+
const lng = dem.west + cur.col * dem.cellSize + dem.cellSize / 2;
|
|
149
|
+
const lat = dem.south + cur.row * dem.cellSize + dem.cellSize / 2;
|
|
150
|
+
affected.push({ lng, lat, elevation: elev, waterDepth: depth });
|
|
151
|
+
const nextLevel = cur.level - 0.01;
|
|
152
|
+
for (const [dr, dc] of [
|
|
153
|
+
[0, 1],
|
|
154
|
+
[0, -1],
|
|
155
|
+
[1, 0],
|
|
156
|
+
[-1, 0]
|
|
157
|
+
]) {
|
|
158
|
+
queue.push({ row: cur.row + dr, col: cur.col + dc, level: nextLevel });
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
const cellArea = dem.cellSize * 111320 * (dem.cellSize * 110540);
|
|
162
|
+
const floodArea = affected.length * cellArea;
|
|
163
|
+
const hull = convexHullLocal(affected.map((c) => [c.lng, c.lat]));
|
|
164
|
+
return {
|
|
165
|
+
source: { lng: params.sourceLng, lat: params.sourceLat },
|
|
166
|
+
floodArea,
|
|
167
|
+
affectedCells: affected,
|
|
168
|
+
hull,
|
|
169
|
+
maxDepth
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
function lngLatToIndex(dem, lng, lat) {
|
|
173
|
+
const col = Math.floor((lng - dem.west) / dem.cellSize);
|
|
174
|
+
const row = Math.floor((lat - dem.south) / dem.cellSize);
|
|
175
|
+
return { row, col };
|
|
176
|
+
}
|
|
177
|
+
function convexHullLocal(points) {
|
|
178
|
+
if (points.length < 3) return [...points];
|
|
179
|
+
const pts = [...points].sort((a, b) => a[0] - b[0] || a[1] - b[1]);
|
|
180
|
+
const cross = (o, a, b) => (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]);
|
|
181
|
+
const lower = [];
|
|
182
|
+
for (const p of pts) {
|
|
183
|
+
while (lower.length >= 2 && cross(lower[lower.length - 2], lower[lower.length - 1], p) <= 0) lower.pop();
|
|
184
|
+
lower.push(p);
|
|
185
|
+
}
|
|
186
|
+
const upper = [];
|
|
187
|
+
for (let i = pts.length - 1; i >= 0; i--) {
|
|
188
|
+
const p = pts[i];
|
|
189
|
+
while (upper.length >= 2 && cross(upper[upper.length - 2], upper[upper.length - 1], p) <= 0) upper.pop();
|
|
190
|
+
upper.push(p);
|
|
191
|
+
}
|
|
192
|
+
upper.pop();
|
|
193
|
+
lower.pop();
|
|
194
|
+
return lower.concat(upper);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// src/leakage/LeakagePlume.ts
|
|
198
|
+
var LeakagePlume = class {
|
|
199
|
+
map;
|
|
200
|
+
thresholds;
|
|
201
|
+
layerPrefix;
|
|
202
|
+
fillColor;
|
|
203
|
+
layerIds = [];
|
|
204
|
+
listeners = /* @__PURE__ */ new Set();
|
|
205
|
+
lastResult = null;
|
|
206
|
+
constructor(options) {
|
|
207
|
+
this.map = options.map;
|
|
208
|
+
this.thresholds = options.thresholds ?? [1e-3, 5e-3, 0.01];
|
|
209
|
+
this.layerPrefix = options.layerPrefix ?? "cg-leakage";
|
|
210
|
+
this.fillColor = options.fillColor ?? "#fb923c";
|
|
211
|
+
}
|
|
212
|
+
/** 燃气泄漏扩散模拟 */
|
|
213
|
+
simulateGas(source, params) {
|
|
214
|
+
const result = gaussianPlume(source, { ...params, thresholds: this.thresholds });
|
|
215
|
+
this.lastResult = result;
|
|
216
|
+
this.renderGas(result);
|
|
217
|
+
for (const l of this.listeners) l(result);
|
|
218
|
+
return result;
|
|
219
|
+
}
|
|
220
|
+
/** 供水爆管淹没模拟 */
|
|
221
|
+
simulateFlood(dem, params) {
|
|
222
|
+
const result = simulateFlood(dem, params);
|
|
223
|
+
this.lastResult = result;
|
|
224
|
+
this.renderFlood(result);
|
|
225
|
+
for (const l of this.listeners) l(result);
|
|
226
|
+
return result;
|
|
227
|
+
}
|
|
228
|
+
/** 清空图层 */
|
|
229
|
+
clear() {
|
|
230
|
+
for (const id of this.layerIds) {
|
|
231
|
+
this.map.removeLayer(id);
|
|
232
|
+
}
|
|
233
|
+
this.layerIds = [];
|
|
234
|
+
}
|
|
235
|
+
/** 销毁组件 */
|
|
236
|
+
destroy() {
|
|
237
|
+
this.clear();
|
|
238
|
+
this.listeners.clear();
|
|
239
|
+
this.lastResult = null;
|
|
240
|
+
}
|
|
241
|
+
/** 订阅结果 */
|
|
242
|
+
onResult(fn) {
|
|
243
|
+
this.listeners.add(fn);
|
|
244
|
+
return () => this.listeners.delete(fn);
|
|
245
|
+
}
|
|
246
|
+
/** 取最后一次结果 */
|
|
247
|
+
getLastResult() {
|
|
248
|
+
return this.lastResult;
|
|
249
|
+
}
|
|
250
|
+
// --------------------------------------------------
|
|
251
|
+
// 内部渲染(GeoJSON 多边形叠加)
|
|
252
|
+
// --------------------------------------------------
|
|
253
|
+
renderGas(result) {
|
|
254
|
+
this.renderContours(
|
|
255
|
+
result.contours.map((c) => ({
|
|
256
|
+
polygon: c.polygon,
|
|
257
|
+
threshold: c.threshold
|
|
258
|
+
})),
|
|
259
|
+
result.source
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
renderFlood(result) {
|
|
263
|
+
if (result.hull.length < 3) return;
|
|
264
|
+
const mlMap = this.map.instance;
|
|
265
|
+
const data = {
|
|
266
|
+
type: "Feature",
|
|
267
|
+
geometry: { type: "Polygon", coordinates: [result.hull] },
|
|
268
|
+
properties: { threshold: 0 }
|
|
269
|
+
};
|
|
270
|
+
const id = `${this.layerPrefix}-flood-fill`;
|
|
271
|
+
if (!mlMap.getSource(id)) mlMap.addSource(id, data);
|
|
272
|
+
try {
|
|
273
|
+
mlMap.addLayer({
|
|
274
|
+
id,
|
|
275
|
+
type: "fill",
|
|
276
|
+
source: id,
|
|
277
|
+
paint: {
|
|
278
|
+
"fill-color": "#3b82f6",
|
|
279
|
+
"fill-opacity": 0.3,
|
|
280
|
+
"fill-outline-color": "#1e40af"
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
this.layerIds.push(id);
|
|
284
|
+
} catch {
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
renderContours(contours, source) {
|
|
288
|
+
const mlMap = this.map.instance;
|
|
289
|
+
const data = {
|
|
290
|
+
type: "FeatureCollection",
|
|
291
|
+
features: contours.filter((c) => c.polygon.length >= 3).map((c) => ({
|
|
292
|
+
type: "Feature",
|
|
293
|
+
geometry: { type: "Polygon", coordinates: [c.polygon] },
|
|
294
|
+
properties: { threshold: c.threshold }
|
|
295
|
+
}))
|
|
296
|
+
};
|
|
297
|
+
const sourceId = `${this.layerPrefix}-gas-src`;
|
|
298
|
+
const layerId = `${this.layerPrefix}-gas-fill`;
|
|
299
|
+
if (!mlMap.getSource(sourceId)) mlMap.addSource(sourceId, data);
|
|
300
|
+
try {
|
|
301
|
+
mlMap.addLayer({
|
|
302
|
+
id: layerId,
|
|
303
|
+
type: "fill",
|
|
304
|
+
source: sourceId,
|
|
305
|
+
paint: {
|
|
306
|
+
"fill-color": [
|
|
307
|
+
"step",
|
|
308
|
+
["get", "threshold"],
|
|
309
|
+
this.fillColor,
|
|
310
|
+
5e-3,
|
|
311
|
+
"#f97316",
|
|
312
|
+
0.01,
|
|
313
|
+
"#ef4444"
|
|
314
|
+
],
|
|
315
|
+
"fill-opacity": 0.35,
|
|
316
|
+
"fill-outline-color": this.fillColor
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
this.layerIds.push(layerId);
|
|
320
|
+
} catch {
|
|
321
|
+
}
|
|
322
|
+
const ptId = `${this.layerPrefix}-source`;
|
|
323
|
+
mlMap.addSource(ptId, {
|
|
324
|
+
type: "FeatureCollection",
|
|
325
|
+
features: [
|
|
326
|
+
{
|
|
327
|
+
type: "Feature",
|
|
328
|
+
geometry: { type: "Point", coordinates: [source.lng, source.lat] },
|
|
329
|
+
properties: {}
|
|
330
|
+
}
|
|
331
|
+
]
|
|
332
|
+
});
|
|
333
|
+
try {
|
|
334
|
+
mlMap.addLayer({
|
|
335
|
+
id: ptId,
|
|
336
|
+
type: "circle",
|
|
337
|
+
source: ptId,
|
|
338
|
+
paint: {
|
|
339
|
+
"circle-radius": 10,
|
|
340
|
+
"circle-color": "#fbbf24",
|
|
341
|
+
"circle-stroke-width": 3,
|
|
342
|
+
"circle-stroke-color": "#000"
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
this.layerIds.push(ptId);
|
|
346
|
+
} catch {
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
exports.LeakagePlume = LeakagePlume;
|
|
352
|
+
exports.classifyFromMeteo = classifyFromMeteo;
|
|
353
|
+
exports.classifyStability = classifyStability;
|
|
354
|
+
exports.dispersionCoefficients = dispersionCoefficients;
|
|
355
|
+
exports.gaussianPlume = gaussianPlume;
|
|
356
|
+
exports.simulateFlood = simulateFlood;
|
|
357
|
+
//# sourceMappingURL=index.cjs.map
|
|
358
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/leakage/pasquillGifford.ts","../../src/leakage/gaussianPlume.ts","../../src/leakage/floodFill.ts","../../src/leakage/LeakagePlume.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Pasquill-Gifford 大气稳定度参数(PRD §4.3.2)\n *\n * 根据风速 + 日射强度 + 夜间云量,对应稳定度类别 A-F\n * A: 极不稳定,B: 不稳定,C: 弱不稳定,D: 中性,E: 弱稳定,F: 稳定\n *\n * 用于高斯烟羽模型的扩散系数 σy/σz 估计。\n */\n\nexport type StabilityClass = 'A' | 'B' | 'C' | 'D' | 'E' | 'F';\n\nexport interface PasquillGiffordParams {\n /** 风速 m/s */\n windSpeed: number;\n /** 日射强度(白天):强/中等/弱 */\n daytimeInsolation?: 'strong' | 'moderate' | 'slight';\n /** 夜间云量(阴天/部分/晴朗) */\n nightCloudCover?: 'overcast' | 'partly' | 'clear';\n /** 是否白天 */\n isDaytime: boolean;\n}\n\n// 修正后的 Pasquill-Gifford 稳定度分类\n// 参考 EPA 工业源空气污染(ISC)模型常用分类\nconst TABLE_DAY: Array<{ wind: number; cls: Record<string, StabilityClass> }> = [\n { wind: 2, cls: { strong: 'A', moderate: 'A', slight: 'B' } },\n { wind: 3, cls: { strong: 'A', moderate: 'B', slight: 'C' } },\n { wind: 5, cls: { strong: 'B', moderate: 'B', slight: 'C' } },\n { wind: 6, cls: { strong: 'C', moderate: 'C', slight: 'D' } },\n { wind: 7, cls: { strong: 'C', moderate: 'D', slight: 'D' } },\n { wind: 999, cls: { strong: 'D', moderate: 'D', slight: 'D' } },\n];\n\nconst TABLE_NIGHT: Array<{ wind: number; cls: Record<string, StabilityClass> }> = [\n { wind: 2, cls: { overcast: 'F', partly: 'F', clear: 'F' } },\n { wind: 3, cls: { overcast: 'E', partly: 'F', clear: 'F' } },\n { wind: 5, cls: { overcast: 'D', partly: 'E', clear: 'F' } },\n { wind: 6, cls: { overcast: 'D', partly: 'D', clear: 'E' } },\n { wind: 999, cls: { overcast: 'D', partly: 'D', clear: 'D' } },\n];\n\n/**\n * 根据 Pasquill-Gifford 表格,确定稳定度类别\n */\nexport function classifyStability(params: PasquillGiffordParams): StabilityClass {\n const table = params.isDaytime ? TABLE_DAY : TABLE_NIGHT;\n const key = params.isDaytime\n ? (params.daytimeInsolation ?? 'moderate')\n : (params.nightCloudCover ?? 'partly');\n\n for (const row of table) {\n if (params.windSpeed < row.wind) return (row.cls as Record<string, StabilityClass>)[key] ?? 'D';\n }\n return 'D';\n}\n\nexport interface DispersionCoefficients {\n /** σy(m),下风向距离 x 的函数 */\n sigmaY: (x: number) => number;\n /** σz(m),下风向距离 x 的函数 */\n sigmaZ: (x: number) => number;\n}\n\n/**\n * Pasquill-Gifford 扩散系数(Briggs 经验公式)\n * σy, σz = a * x / √(1 + b*x)\n *\n * x 单位 km(外部调用时换算:x (m) / 1000)\n *\n * 表格源自 USEPA ISC3 模型常用设置(单位: m/km 与 1/km)\n */\nexport function dispersionCoefficients(stability: StabilityClass): DispersionCoefficients {\n // [σy 前系数, σy 分母修正系数, σz 前系数, σz 分母修正系数]\n const params: Record<StabilityClass, [number, number, number, number]> = {\n A: [0.22, 0.0001, 0.20, 0.000],\n B: [0.16, 0.0001, 0.12, 0.000],\n C: [0.11, 0.0001, 0.08, 0.0002],\n D: [0.08, 0.0001, 0.06, 0.0015],\n E: [0.06, 0.0001, 0.03, 0.0003],\n F: [0.04, 0.0001, 0.016, 0.0003],\n };\n const [a, b, c, d] = params[stability];\n return {\n sigmaY: (xMeters: number) => {\n const xKm = xMeters / 1000;\n return (a * xKm) / Math.sqrt(1 + b * xKm) * 1000;\n },\n sigmaZ: (xMeters: number) => {\n const xKm = xMeters / 1000;\n return (c * xKm) / Math.sqrt(1 + d * xKm) * 1000;\n },\n };\n}\n","/**\n * 高斯烟羽模型(Gaussian Plume)\n *\n * 用于燃气泄漏扩散模拟(PRD §4.3.2):\n * C(x, y, z) = Q / (2π · σy · σz · u) × exp(-y²/2σy²) ×\n * [exp(-(z-H)²/2σz²) + exp(-(z+H)²/2σz²)]\n *\n * 输入:\n * - sourceCoord(泄漏点):lng/lat\n * - Q:泄漏速率(kg/s)\n * - u:风速(m/s)\n * - windDirection:风向(弧度,0=东)\n * - stability:大气稳定度 A-F\n * - H:泄漏源高度(m)\n * - threshold:警戒浓度(如 20%LEL)\n *\n * 输出:\n * - 等浓度线多边形(不同浓度等级)\n * - 下风向最大影响距离\n */\n\nimport type { DispersionCoefficients } from './pasquillGifford';\nimport { dispersionCoefficients, classifyStability } from './pasquillGifford';\n\nexport interface GasLeakParams {\n /** 风向(弧度,0=东,PI/2=北) */\n windDirection: number;\n /** 风速 m/s */\n windSpeed: number;\n /** 泄漏速率 kg/s */\n leakRate: number;\n /** 释放高度 m */\n releaseHeight: number;\n /** 大气稳定度(可选,不传则自动分类) */\n stability?: 'A' | 'B' | 'C' | 'D' | 'E' | 'F';\n /** 浓度阈值(kg/m³)列表 */\n thresholds?: number[];\n /** 网格步长(m)默认 50 */\n gridStep?: number;\n /** 计算范围(m)默认 5000 */\n range?: number;\n}\n\nexport interface GasLeakResult {\n /** 泄漏点 */\n source: { lng: number; lat: number };\n /** 风向(弧度) */\n windDirection: number;\n /** 风速 m/s */\n windSpeed: number;\n /** 大气稳定度 */\n stability: 'A' | 'B' | 'C' | 'D' | 'E' | 'F';\n /** 等浓度线多边形(阈值对应) */\n contours: ConcentrationContour[];\n /** 下风向最大影响距离(m) */\n maxDownwindDistance: number;\n}\n\nexport interface ConcentrationContour {\n /** 阈值 */\n threshold: number;\n /** 多边形(顺时针 GeoJSON-like) */\n polygon: [number, number][];\n /** 是否闭合 */\n closed: boolean;\n}\n\n/**\n * 计算泄漏源下风向的浓度分布,输出等浓度线多边形\n */\nexport function gaussianPlume(\n source: { lng: number; lat: number },\n params: GasLeakParams\n): GasLeakResult {\n const stability = params.stability ?? 'D';\n const { sigmaY, sigmaZ } = dispersionCoefficients(stability);\n const thresholds = params.thresholds ?? [0.001, 0.005, 0.01];\n const step = params.gridStep ?? 50;\n const range = params.range ?? 5000;\n\n const contourList: ConcentrationContour[] = thresholds.map((t) => ({\n threshold: t,\n polygon: [],\n closed: false,\n }));\n\n // 采样网格:下风向 + 横向\n // 用极坐标(r, theta)→ 转笛卡尔 → lng/lat\n const Q = params.leakRate;\n const u = params.windSpeed;\n const H = params.releaseHeight;\n\n let maxDownwindDistance = 0;\n\n for (const c of contourList) {\n const points: [number, number][] = [];\n // 从近到远扫描 r,找满足 c(r) >= threshold 的最大 r\n for (let r = step; r <= range; r += step) {\n const sy = sigmaY(r);\n const sz = sigmaZ(r);\n if (sy <= 0 || sz <= 0) continue;\n const concCenter = Q / (2 * Math.PI * sy * sz * u);\n const zTerm = 2 * Math.exp(-(H * H) / (2 * sz * sz));\n const cMax = concCenter * zTerm;\n if (cMax >= c.threshold) {\n points.push([r, 0]);\n if (r > maxDownwindDistance) maxDownwindDistance = r;\n }\n }\n\n // 多边形 = 各 r 对应的横向扩展(在每个 r 处 y 范围由 σy 决定)\n const poly: [number, number][] = [];\n for (let r = step; r <= range; r += step) {\n const sy = sigmaY(r);\n if (sy <= 0) continue;\n const syy = Q / (2 * Math.PI * sy * sigmaZ(r) * u) * 2;\n if (syy < c.threshold) continue;\n // 横向浓度 = (Q / 2πσyσzu) × exp(-y²/2σy²) × 2\n // 解出 y:exp(-y²/2σy²) = c.threshold * 2πσyσzu / Q\n // y² = -2σy² ln(...)\n const ratio = (c.threshold * Math.PI * sy * sigmaZ(r) * u) / Q;\n if (ratio >= 1) continue; // 浓度太弱,不存在等值线\n const yMax = sy * Math.sqrt(-2 * Math.log(ratio));\n poly.push([r, yMax]);\n poly.unshift([r, -yMax]);\n }\n c.polygon = polyToLngLat(source, params.windDirection, poly);\n c.closed = poly.length >= 3;\n }\n\n return {\n source,\n windDirection: params.windDirection,\n windSpeed: params.windSpeed,\n stability,\n contours: contourList,\n maxDownwindDistance,\n };\n}\n\n/** 把 (r, y) 极坐标点转换为 (lng, lat) */\nfunction polyToLngLat(\n source: { lng: number; lat: number },\n windDir: number,\n poly: [number, number][]\n): [number, number][] {\n return poly.map(([r, y]) => {\n // 下风向 = windDir 方向;横向 = windDir - π/2(垂直右)\n // 设下风向单位向量 (cosθ, sinθ),横向单位向量 (-sinθ, cosθ)\n // 笛卡尔:dx = r * cosθ + y * (-sinθ), dy = r * sinθ + y * cosθ\n const cosW = Math.cos(windDir);\n const sinW = Math.sin(windDir);\n const dx = r * cosW + y * -sinW;\n const dy = r * sinW + y * cosW;\n\n const dLat = dy / 110540;\n const dLng = dx / (111320 * Math.cos((source.lat * Math.PI) / 180));\n return [source.lng + dLng, source.lat + dLat];\n });\n}\n\n/** 根据气象数据自动确定稳定度类别(便利入口) */\nexport function classifyFromMeteo(opts: {\n windSpeed: number;\n isDaytime: boolean;\n daytimeInsolation?: 'strong' | 'moderate' | 'slight';\n nightCloudCover?: 'overcast' | 'partly' | 'clear';\n}) {\n return classifyStability(opts);\n}\n\nexport { dispersionCoefficients };\nexport type { DispersionCoefficients };\n","/**\n * 供水爆管淹没分析(基于地形的 flood fill)\n *\n * 输入:\n * - DEM:高程网格(lng, lat → elevation)\n * - source:爆管点\n * - 网格分辨率\n *\n * 算法:\n * - 从爆管点出发,flood fill 到相邻低洼地\n * - 估算淹没范围\n */\n\nexport interface DemGrid {\n /** 西南角 lng/lat */\n west: number;\n south: number;\n /** 网格行列数 */\n cols: number;\n rows: number;\n /** 单元尺寸(度) */\n cellSize: number;\n /** 高程数组(row-major,rows × cols) */\n elevations: number[];\n}\n\nexport interface FloodParams {\n sourceLng: number;\n sourceLat: number;\n /** 起始水位(m),默认 0 */\n initialWaterLevel?: number;\n /** 模拟时长(秒),默认 30min */\n duration?: number;\n /** 流量估算(m³/h),默认按中等爆管 50 */\n flowRate?: number;\n}\n\nexport interface FloodResult {\n source: { lng: number; lat: number };\n /** 淹没面积(m²) */\n floodArea: number;\n /** 受影响网格(高程 < 水位) */\n affectedCells: Array<{ lng: number; lat: number; elevation: number; waterDepth: number }>;\n /** 凸包多边形 */\n hull: [number, number][];\n /** 最大水深 */\n maxDepth: number;\n}\n\n/**\n * 简单 flood fill 模拟(按等高线分布)\n */\nexport function simulateFlood(dem: DemGrid, params: FloodParams): FloodResult {\n const t0 = Date.now();\n const sourceIdx = lngLatToIndex(dem, params.sourceLng, params.sourceLat);\n if (sourceIdx.row < 0 || sourceIdx.row >= dem.rows || sourceIdx.col < 0 || sourceIdx.col >= dem.cols) {\n return {\n source: { lng: params.sourceLng, lat: params.sourceLat },\n floodArea: 0,\n affectedCells: [],\n hull: [],\n maxDepth: 0,\n };\n }\n\n const sourceElev = dem.elevations[sourceIdx.row * dem.cols + sourceIdx.col] ?? 0;\n const durationMin = (params.duration ?? 30 * 60) / 60; // s → min\n const flowM3h = params.flowRate ?? 50;\n const volumeM3 = flowM3h * (durationMin / 60); // m³\n const initialLevel = params.initialWaterLevel ?? sourceElev + 0.05;\n\n // 简化:假设水平摊开,直至水量耗尽或边界阻挡\n const visited = new Set<number>();\n const affected: FloodResult['affectedCells'] = [];\n const queue: Array<{ row: number; col: number; level: number }> = [];\n queue.push({ row: sourceIdx.row, col: sourceIdx.col, level: initialLevel });\n\n let maxDepth = 0;\n\n while (queue.length > 0) {\n const cur = queue.shift()!;\n const idx = cur.row * dem.cols + cur.col;\n if (visited.has(idx)) continue;\n visited.add(idx);\n\n if (cur.row < 0 || cur.row >= dem.rows) continue;\n if (cur.col < 0 || cur.col >= dem.cols) continue;\n\n const elev = dem.elevations[idx] ?? 0;\n const depth = cur.level - elev;\n if (depth <= 0) continue;\n if (depth > maxDepth) maxDepth = depth;\n\n const lng = dem.west + cur.col * dem.cellSize + dem.cellSize / 2;\n const lat = dem.south + cur.row * dem.cellSize + dem.cellSize / 2;\n affected.push({ lng, lat, elevation: elev, waterDepth: depth });\n\n // 4 邻居\n const nextLevel = cur.level - 0.01;\n for (const [dr, dc] of [\n [0, 1],\n [0, -1],\n [1, 0],\n [-1, 0],\n ] as Array<[number, number]>) {\n queue.push({ row: cur.row + dr, col: cur.col + dc, level: nextLevel });\n }\n }\n\n const cellArea = (dem.cellSize * 111320) * (dem.cellSize * 110540);\n const floodArea = affected.length * cellArea;\n\n const hull: [number, number][] = convexHullLocal(affected.map((c) => [c.lng, c.lat]));\n\n return {\n source: { lng: params.sourceLng, lat: params.sourceLat },\n floodArea,\n affectedCells: affected,\n hull,\n maxDepth,\n };\n}\n\nfunction lngLatToIndex(dem: DemGrid, lng: number, lat: number): { row: number; col: number } {\n const col = Math.floor((lng - dem.west) / dem.cellSize);\n const row = Math.floor((lat - dem.south) / dem.cellSize);\n return { row, col };\n}\n\nfunction convexHullLocal(points: [number, number][]): [number, number][] {\n if (points.length < 3) return [...points];\n const pts = [...points].sort((a, b) => (a[0] - b[0]) || (a[1] - b[1]));\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 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) lower.pop();\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) upper.pop();\n upper.push(p);\n }\n upper.pop();\n lower.pop();\n return lower.concat(upper);\n}\n","/**\n * LeakagePlume 组件类(占位 stub)\n *\n * Phase 1 MVP 完整功能待 M6 W1-W2 完成。\n * 当前 stub 仅暴露 API 接口和最小实现。\n */\n\nimport type { Map as CaoguoMap } from '@caoguo/maplibre';\nimport type { GasLeakParams, GasLeakResult } from './gaussianPlume';\nimport { gaussianPlume } from './gaussianPlume';\nimport type { FloodParams, FloodResult } from './floodFill';\nimport { simulateFlood } from './floodFill';\nimport type { DemGrid } from './floodFill';\n\nexport type { GasLeakParams, GasLeakResult, FloodParams, FloodResult, DemGrid };\n\nexport interface LeakagePlumeOptions {\n map: CaoguoMap;\n /** 浓度阈值(kg/m³),可分级 */\n thresholds?: number[];\n /** 层 ID 前缀 */\n layerPrefix?: string;\n /** 区域填充色 */\n fillColor?: string;\n}\n\ntype Listener = (r: GasLeakResult | FloodResult) => void;\n\n/**\n * LeakagePlume 组件(燃气泄漏 / 供水爆管)\n *\n * 用法:\n * const plume = new LeakagePlume({ map });\n * plume.simulateGas({ lng, lat }, { windDirection: 1.5, windSpeed: 3, ... });\n * plume.simulateFlood(demGrid, { sourceLng, sourceLat });\n */\nexport class LeakagePlume {\n private map: CaoguoMap;\n private thresholds: number[];\n private layerPrefix: string;\n private fillColor: string;\n private layerIds: string[] = [];\n private listeners = new Set<Listener>();\n private lastResult: GasLeakResult | FloodResult | null = null;\n\n constructor(options: LeakagePlumeOptions) {\n this.map = options.map;\n this.thresholds = options.thresholds ?? [0.001, 0.005, 0.01];\n this.layerPrefix = options.layerPrefix ?? 'cg-leakage';\n this.fillColor = options.fillColor ?? '#fb923c';\n }\n\n /** 燃气泄漏扩散模拟 */\n simulateGas(\n source: { lng: number; lat: number },\n params: Omit<GasLeakParams, 'thresholds'>\n ): GasLeakResult {\n const result = gaussianPlume(source, { ...params, thresholds: this.thresholds });\n this.lastResult = result;\n this.renderGas(result);\n for (const l of this.listeners) l(result);\n return result;\n }\n\n /** 供水爆管淹没模拟 */\n simulateFlood(dem: DemGrid, params: FloodParams): FloodResult {\n const result = simulateFlood(dem, params);\n this.lastResult = result;\n this.renderFlood(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(): GasLeakResult | FloodResult | null {\n return this.lastResult;\n }\n\n // --------------------------------------------------\n // 内部渲染(GeoJSON 多边形叠加)\n // --------------------------------------------------\n private renderGas(result: GasLeakResult): void {\n this.renderContours(\n result.contours.map((c) => ({\n polygon: c.polygon,\n threshold: c.threshold,\n })),\n result.source\n );\n }\n\n private renderFlood(result: FloodResult): void {\n if (result.hull.length < 3) return;\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 data: GeoJSON.Feature<GeoJSON.Polygon> = {\n type: 'Feature',\n geometry: { type: 'Polygon', coordinates: [result.hull] },\n properties: { threshold: 0 },\n };\n\n const id = `${this.layerPrefix}-flood-fill`;\n if (!mlMap.getSource(id)) mlMap.addSource(id, data);\n try {\n mlMap.addLayer({\n id,\n type: 'fill',\n source: id,\n paint: {\n 'fill-color': '#3b82f6',\n 'fill-opacity': 0.3,\n 'fill-outline-color': '#1e40af',\n },\n });\n this.layerIds.push(id);\n } catch {\n // ignore\n }\n }\n\n private renderContours(\n contours: Array<{ polygon: [number, number][]; threshold: number }>,\n source: { lng: number; lat: number }\n ): void {\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 data: GeoJSON.FeatureCollection<GeoJSON.Polygon> = {\n type: 'FeatureCollection',\n features: contours\n .filter((c) => c.polygon.length >= 3)\n .map((c) => ({\n type: 'Feature' as const,\n geometry: { type: 'Polygon' as const, coordinates: [c.polygon] },\n properties: { threshold: c.threshold },\n })),\n };\n\n const sourceId = `${this.layerPrefix}-gas-src`;\n const layerId = `${this.layerPrefix}-gas-fill`;\n if (!mlMap.getSource(sourceId)) mlMap.addSource(sourceId, data);\n try {\n mlMap.addLayer({\n id: layerId,\n type: 'fill',\n source: sourceId,\n paint: {\n 'fill-color': [\n 'step',\n ['get', 'threshold'],\n this.fillColor,\n 0.005,\n '#f97316',\n 0.01,\n '#ef4444',\n ] as unknown,\n 'fill-opacity': 0.35,\n 'fill-outline-color': this.fillColor,\n },\n });\n this.layerIds.push(layerId);\n } catch {\n // ignore\n }\n\n // 标记泄漏点\n const ptId = `${this.layerPrefix}-source`;\n mlMap.addSource(ptId, {\n type: 'FeatureCollection',\n features: [\n {\n type: 'Feature',\n geometry: { type: 'Point', coordinates: [source.lng, source.lat] },\n properties: {},\n },\n ],\n });\n try {\n mlMap.addLayer({\n id: ptId,\n type: 'circle',\n source: ptId,\n paint: {\n 'circle-radius': 10,\n 'circle-color': '#fbbf24',\n 'circle-stroke-width': 3,\n 'circle-stroke-color': '#000',\n },\n });\n this.layerIds.push(ptId);\n } catch {\n // ignore\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { Map } from '@caoguo/maplibre';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Pasquill-Gifford 大气稳定度参数(PRD §4.3.2)
|
|
5
|
+
*
|
|
6
|
+
* 根据风速 + 日射强度 + 夜间云量,对应稳定度类别 A-F
|
|
7
|
+
* A: 极不稳定,B: 不稳定,C: 弱不稳定,D: 中性,E: 弱稳定,F: 稳定
|
|
8
|
+
*
|
|
9
|
+
* 用于高斯烟羽模型的扩散系数 σy/σz 估计。
|
|
10
|
+
*/
|
|
11
|
+
type StabilityClass = 'A' | 'B' | 'C' | 'D' | 'E' | 'F';
|
|
12
|
+
interface PasquillGiffordParams {
|
|
13
|
+
/** 风速 m/s */
|
|
14
|
+
windSpeed: number;
|
|
15
|
+
/** 日射强度(白天):强/中等/弱 */
|
|
16
|
+
daytimeInsolation?: 'strong' | 'moderate' | 'slight';
|
|
17
|
+
/** 夜间云量(阴天/部分/晴朗) */
|
|
18
|
+
nightCloudCover?: 'overcast' | 'partly' | 'clear';
|
|
19
|
+
/** 是否白天 */
|
|
20
|
+
isDaytime: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* 根据 Pasquill-Gifford 表格,确定稳定度类别
|
|
24
|
+
*/
|
|
25
|
+
declare function classifyStability(params: PasquillGiffordParams): StabilityClass;
|
|
26
|
+
interface DispersionCoefficients {
|
|
27
|
+
/** σy(m),下风向距离 x 的函数 */
|
|
28
|
+
sigmaY: (x: number) => number;
|
|
29
|
+
/** σz(m),下风向距离 x 的函数 */
|
|
30
|
+
sigmaZ: (x: number) => number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Pasquill-Gifford 扩散系数(Briggs 经验公式)
|
|
34
|
+
* σy, σz = a * x / √(1 + b*x)
|
|
35
|
+
*
|
|
36
|
+
* x 单位 km(外部调用时换算:x (m) / 1000)
|
|
37
|
+
*
|
|
38
|
+
* 表格源自 USEPA ISC3 模型常用设置(单位: m/km 与 1/km)
|
|
39
|
+
*/
|
|
40
|
+
declare function dispersionCoefficients(stability: StabilityClass): DispersionCoefficients;
|
|
41
|
+
|
|
42
|
+
interface GasLeakParams {
|
|
43
|
+
/** 风向(弧度,0=东,PI/2=北) */
|
|
44
|
+
windDirection: number;
|
|
45
|
+
/** 风速 m/s */
|
|
46
|
+
windSpeed: number;
|
|
47
|
+
/** 泄漏速率 kg/s */
|
|
48
|
+
leakRate: number;
|
|
49
|
+
/** 释放高度 m */
|
|
50
|
+
releaseHeight: number;
|
|
51
|
+
/** 大气稳定度(可选,不传则自动分类) */
|
|
52
|
+
stability?: 'A' | 'B' | 'C' | 'D' | 'E' | 'F';
|
|
53
|
+
/** 浓度阈值(kg/m³)列表 */
|
|
54
|
+
thresholds?: number[];
|
|
55
|
+
/** 网格步长(m)默认 50 */
|
|
56
|
+
gridStep?: number;
|
|
57
|
+
/** 计算范围(m)默认 5000 */
|
|
58
|
+
range?: number;
|
|
59
|
+
}
|
|
60
|
+
interface GasLeakResult {
|
|
61
|
+
/** 泄漏点 */
|
|
62
|
+
source: {
|
|
63
|
+
lng: number;
|
|
64
|
+
lat: number;
|
|
65
|
+
};
|
|
66
|
+
/** 风向(弧度) */
|
|
67
|
+
windDirection: number;
|
|
68
|
+
/** 风速 m/s */
|
|
69
|
+
windSpeed: number;
|
|
70
|
+
/** 大气稳定度 */
|
|
71
|
+
stability: 'A' | 'B' | 'C' | 'D' | 'E' | 'F';
|
|
72
|
+
/** 等浓度线多边形(阈值对应) */
|
|
73
|
+
contours: ConcentrationContour[];
|
|
74
|
+
/** 下风向最大影响距离(m) */
|
|
75
|
+
maxDownwindDistance: number;
|
|
76
|
+
}
|
|
77
|
+
interface ConcentrationContour {
|
|
78
|
+
/** 阈值 */
|
|
79
|
+
threshold: number;
|
|
80
|
+
/** 多边形(顺时针 GeoJSON-like) */
|
|
81
|
+
polygon: [number, number][];
|
|
82
|
+
/** 是否闭合 */
|
|
83
|
+
closed: boolean;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* 计算泄漏源下风向的浓度分布,输出等浓度线多边形
|
|
87
|
+
*/
|
|
88
|
+
declare function gaussianPlume(source: {
|
|
89
|
+
lng: number;
|
|
90
|
+
lat: number;
|
|
91
|
+
}, params: GasLeakParams): GasLeakResult;
|
|
92
|
+
/** 根据气象数据自动确定稳定度类别(便利入口) */
|
|
93
|
+
declare function classifyFromMeteo(opts: {
|
|
94
|
+
windSpeed: number;
|
|
95
|
+
isDaytime: boolean;
|
|
96
|
+
daytimeInsolation?: 'strong' | 'moderate' | 'slight';
|
|
97
|
+
nightCloudCover?: 'overcast' | 'partly' | 'clear';
|
|
98
|
+
}): StabilityClass;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* 供水爆管淹没分析(基于地形的 flood fill)
|
|
102
|
+
*
|
|
103
|
+
* 输入:
|
|
104
|
+
* - DEM:高程网格(lng, lat → elevation)
|
|
105
|
+
* - source:爆管点
|
|
106
|
+
* - 网格分辨率
|
|
107
|
+
*
|
|
108
|
+
* 算法:
|
|
109
|
+
* - 从爆管点出发,flood fill 到相邻低洼地
|
|
110
|
+
* - 估算淹没范围
|
|
111
|
+
*/
|
|
112
|
+
interface DemGrid {
|
|
113
|
+
/** 西南角 lng/lat */
|
|
114
|
+
west: number;
|
|
115
|
+
south: number;
|
|
116
|
+
/** 网格行列数 */
|
|
117
|
+
cols: number;
|
|
118
|
+
rows: number;
|
|
119
|
+
/** 单元尺寸(度) */
|
|
120
|
+
cellSize: number;
|
|
121
|
+
/** 高程数组(row-major,rows × cols) */
|
|
122
|
+
elevations: number[];
|
|
123
|
+
}
|
|
124
|
+
interface FloodParams {
|
|
125
|
+
sourceLng: number;
|
|
126
|
+
sourceLat: number;
|
|
127
|
+
/** 起始水位(m),默认 0 */
|
|
128
|
+
initialWaterLevel?: number;
|
|
129
|
+
/** 模拟时长(秒),默认 30min */
|
|
130
|
+
duration?: number;
|
|
131
|
+
/** 流量估算(m³/h),默认按中等爆管 50 */
|
|
132
|
+
flowRate?: number;
|
|
133
|
+
}
|
|
134
|
+
interface FloodResult {
|
|
135
|
+
source: {
|
|
136
|
+
lng: number;
|
|
137
|
+
lat: number;
|
|
138
|
+
};
|
|
139
|
+
/** 淹没面积(m²) */
|
|
140
|
+
floodArea: number;
|
|
141
|
+
/** 受影响网格(高程 < 水位) */
|
|
142
|
+
affectedCells: Array<{
|
|
143
|
+
lng: number;
|
|
144
|
+
lat: number;
|
|
145
|
+
elevation: number;
|
|
146
|
+
waterDepth: number;
|
|
147
|
+
}>;
|
|
148
|
+
/** 凸包多边形 */
|
|
149
|
+
hull: [number, number][];
|
|
150
|
+
/** 最大水深 */
|
|
151
|
+
maxDepth: number;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* 简单 flood fill 模拟(按等高线分布)
|
|
155
|
+
*/
|
|
156
|
+
declare function simulateFlood(dem: DemGrid, params: FloodParams): FloodResult;
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* LeakagePlume 组件类(占位 stub)
|
|
160
|
+
*
|
|
161
|
+
* Phase 1 MVP 完整功能待 M6 W1-W2 完成。
|
|
162
|
+
* 当前 stub 仅暴露 API 接口和最小实现。
|
|
163
|
+
*/
|
|
164
|
+
|
|
165
|
+
interface LeakagePlumeOptions {
|
|
166
|
+
map: Map;
|
|
167
|
+
/** 浓度阈值(kg/m³),可分级 */
|
|
168
|
+
thresholds?: number[];
|
|
169
|
+
/** 层 ID 前缀 */
|
|
170
|
+
layerPrefix?: string;
|
|
171
|
+
/** 区域填充色 */
|
|
172
|
+
fillColor?: string;
|
|
173
|
+
}
|
|
174
|
+
type Listener = (r: GasLeakResult | FloodResult) => void;
|
|
175
|
+
/**
|
|
176
|
+
* LeakagePlume 组件(燃气泄漏 / 供水爆管)
|
|
177
|
+
*
|
|
178
|
+
* 用法:
|
|
179
|
+
* const plume = new LeakagePlume({ map });
|
|
180
|
+
* plume.simulateGas({ lng, lat }, { windDirection: 1.5, windSpeed: 3, ... });
|
|
181
|
+
* plume.simulateFlood(demGrid, { sourceLng, sourceLat });
|
|
182
|
+
*/
|
|
183
|
+
declare class LeakagePlume {
|
|
184
|
+
private map;
|
|
185
|
+
private thresholds;
|
|
186
|
+
private layerPrefix;
|
|
187
|
+
private fillColor;
|
|
188
|
+
private layerIds;
|
|
189
|
+
private listeners;
|
|
190
|
+
private lastResult;
|
|
191
|
+
constructor(options: LeakagePlumeOptions);
|
|
192
|
+
/** 燃气泄漏扩散模拟 */
|
|
193
|
+
simulateGas(source: {
|
|
194
|
+
lng: number;
|
|
195
|
+
lat: number;
|
|
196
|
+
}, params: Omit<GasLeakParams, 'thresholds'>): GasLeakResult;
|
|
197
|
+
/** 供水爆管淹没模拟 */
|
|
198
|
+
simulateFlood(dem: DemGrid, params: FloodParams): FloodResult;
|
|
199
|
+
/** 清空图层 */
|
|
200
|
+
clear(): void;
|
|
201
|
+
/** 销毁组件 */
|
|
202
|
+
destroy(): void;
|
|
203
|
+
/** 订阅结果 */
|
|
204
|
+
onResult(fn: Listener): () => void;
|
|
205
|
+
/** 取最后一次结果 */
|
|
206
|
+
getLastResult(): GasLeakResult | FloodResult | null;
|
|
207
|
+
private renderGas;
|
|
208
|
+
private renderFlood;
|
|
209
|
+
private renderContours;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export { type ConcentrationContour, type DemGrid, type DispersionCoefficients, type FloodParams, type FloodResult, type GasLeakParams, type GasLeakResult, LeakagePlume, type LeakagePlumeOptions, type PasquillGiffordParams, type StabilityClass, classifyFromMeteo, classifyStability, dispersionCoefficients, gaussianPlume, simulateFlood };
|