@caoguo/maplibre-pipeline 0.0.4 → 0.0.5

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.
@@ -217,10 +217,10 @@ var PipelineHealth = class {
217
217
  const input = {
218
218
  installDate: p.properties?.installDate,
219
219
  material: p.properties?.material,
220
- failureCount: void 0,
220
+ failureCount: p.properties?.failureCount ?? 0,
221
221
  pressure: p.properties?.pressure,
222
222
  ratedPressure: p.properties?.ratedPressure,
223
- hasCathodicProtection: void 0,
223
+ hasCathodicProtection: p.properties?.hasCathodicProtection ?? false,
224
224
  status: p.properties?.status
225
225
  };
226
226
  return { pipeId: p.id, score: scorePipeHealth(input, weights) };
@@ -336,5 +336,5 @@ var PipelineHealth = class {
336
336
  };
337
337
 
338
338
  export { DEFAULT_WEIGHTS, PipelineHealth, aggregateHeatmap, heatmapToGeoJSON, prioritizeMaintenance, scorePipeHealth, scorePipes };
339
- //# sourceMappingURL=chunk-VA2TQWL3.js.map
340
- //# sourceMappingURL=chunk-VA2TQWL3.js.map
339
+ //# sourceMappingURL=chunk-3656CGXE.js.map
340
+ //# sourceMappingURL=chunk-3656CGXE.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/health/healthScorer.ts","../src/health/riskHeatmap.ts","../src/health/PipelineHealth.ts"],"names":[],"mappings":"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","file":"chunk-VA2TQWL3.js","sourcesContent":["/**\n * 管线健康度评分(healthScorer)\n *\n * 6 维加权评分(PRD §4.4.2):\n * health_score = age (0.25) + material (0.20) + soil (0.15) +\n * history (0.20) + pressure (0.10) + protection (0.10)\n *\n * 每维 0-100,最终加权求和。\n * 评分模型可解释:每个维度的评分依据清晰可见。\n */\n\nimport type { PipeMaterial, PipeStatus } from '../types';\n\nexport interface PipeHealthInput {\n /** 安装日期 ISO */\n installDate?: string;\n /** 材质 */\n material?: PipeMaterial;\n /** 当前故障次数 */\n failureCount?: number;\n /** 当前压力(MPa) */\n pressure?: number;\n /** 最高允许压力(MPa) */\n ratedPressure?: number;\n /** 是否阴极保护 */\n hasCathodicProtection?: boolean;\n /** 土壤腐蚀指数 0-1(无数据时 0.5) */\n soilCorrosion?: number;\n /** 状态(damaged / under_repair 直接影响评分) */\n status?: PipeStatus;\n}\n\nexport interface PipeHealthScore {\n /** 总分 0-100 */\n score: number;\n /** 等级 */\n level: 'excellent' | 'good' | 'fair' | 'poor' | 'critical';\n /** 6 维细分 */\n dimensions: {\n age: { score: number; weight: number; reason: string };\n material: { score: number; weight: number; reason: string };\n soil: { score: number; weight: number; reason: string };\n history: { score: number; weight: number; reason: string };\n pressure: { score: number; weight: number; reason: string };\n protection: { score: number; weight: number; reason: string };\n };\n}\n\n/** 默认权重 */\nexport const DEFAULT_WEIGHTS = {\n age: 0.25,\n material: 0.2,\n soil: 0.15,\n history: 0.2,\n pressure: 0.1,\n protection: 0.1,\n};\n\nconst MATERIAL_RISK: Record<PipeMaterial, number> = {\n cast_iron: 0.85, // 铸铁 = 高风险(旧管网)\n ductile_iron: 0.2, // 球墨铸铁\n steel: 0.4,\n pe: 0.1,\n pvc: 0.15,\n concrete: 0.3,\n hdpe: 0.05,\n copper: 0.1,\n unknown: 0.5,\n};\n\n/**\n * 计算单根管线的健康度\n */\nexport function scorePipeHealth(input: PipeHealthInput, weights = DEFAULT_WEIGHTS): PipeHealthScore {\n const dims = {\n age: scoreAge(input, weights.age),\n material: scoreMaterial(input, weights.material),\n soil: scoreSoil(input, weights.soil),\n history: scoreHistory(input, weights.history),\n pressure: scorePressure(input, weights.pressure),\n protection: scoreProtection(input, weights.protection),\n };\n\n const total =\n dims.age.score * dims.age.weight +\n dims.material.score * dims.material.weight +\n dims.soil.score * dims.soil.weight +\n dims.history.score * dims.history.weight +\n dims.pressure.score * dims.pressure.weight +\n dims.protection.score * dims.protection.weight;\n\n // 损坏或维修中额外惩罚\n let final = total;\n if (input.status === 'damaged') final *= 0.5;\n else if (input.status === 'under_repair') final *= 0.7;\n else if (input.status === 'abandoned') final = 0;\n\n return {\n score: Math.round(final),\n level: toLevel(final),\n dimensions: dims,\n };\n}\n\nfunction toLevel(score: number): PipeHealthScore['level'] {\n if (score >= 80) return 'excellent';\n if (score >= 60) return 'good';\n if (score >= 40) return 'fair';\n if (score >= 20) return 'poor';\n return 'critical';\n}\n\nfunction scoreAge(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['age'] {\n if (!input.installDate) {\n return { score: 50, weight, reason: '未知安装日期,按中等计' };\n }\n const ageYears = (Date.now() - new Date(input.installDate).getTime()) / (365.25 * 24 * 3600 * 1000);\n if (ageYears < 0) return { score: 100, weight, reason: '未来日期,视为优秀' };\n if (ageYears < 5) return { score: 100, weight, reason: '新建管线 (<5年)' };\n if (ageYears < 15) return { score: 85, weight, reason: '较新 (5-15年)' };\n if (ageYears < 25) return { score: 65, weight, reason: '中龄 (15-25年)' };\n if (ageYears < 40) return { score: 40, weight, reason: '老龄 (25-40年)' };\n if (ageYears < 60) return { score: 20, weight, reason: '超期 (>40年)' };\n return { score: 5, weight, reason: '超期 (>60年)' };\n}\n\nfunction scoreMaterial(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['material'] {\n if (!input.material) {\n return { score: 50, weight, reason: '未知材质,按中等计' };\n }\n const risk = MATERIAL_RISK[input.material] ?? 0.5;\n const score = Math.round((1 - risk) * 100);\n const labels: Record<string, string> = {\n cast_iron: '铸铁(高风险)',\n ductile_iron: '球墨铸铁',\n steel: '钢',\n pe: 'PE(低风险)',\n pvc: 'PVC',\n concrete: '混凝土',\n hdpe: 'HDPE(最佳)',\n copper: '铜',\n unknown: '未知',\n };\n return {\n score,\n weight,\n reason: labels[input.material] ?? input.material,\n };\n}\n\nfunction scoreSoil(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['soil'] {\n const c = input.soilCorrosion ?? 0.5;\n const score = Math.round((1 - c) * 100);\n return {\n score,\n weight,\n reason: c === 0.5 && !input.soilCorrosion ? '无土壤数据,按平均计' : `土壤腐蚀指数 ${c.toFixed(2)}`,\n };\n}\n\nfunction scoreHistory(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['history'] {\n const fail = input.failureCount ?? 0;\n if (fail === 0) return { score: 100, weight, reason: '历史无故障' };\n if (fail === 1) return { score: 75, weight, reason: '历史 1 次故障' };\n if (fail === 2) return { score: 50, weight, reason: '历史 2 次故障' };\n if (fail === 3) return { score: 25, weight, reason: '历史 3 次故障' };\n return { score: 0, weight, reason: `历史 ≥${fail} 次故障` };\n}\n\nfunction scorePressure(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['pressure'] {\n if (!input.pressure) {\n return { score: 75, weight, reason: '无压力数据,按中等偏好计' };\n }\n if (!input.ratedPressure) {\n return { score: 75, weight, reason: '仅知当前压力' };\n }\n const ratio = input.pressure / input.ratedPressure;\n if (ratio < 0.5) return { score: 60, weight, reason: '压力偏低 (使用率 <50%)' };\n if (ratio < 0.8) return { score: 90, weight, reason: '压力正常 (使用率 50-80%)' };\n if (ratio < 1.0) return { score: 75, weight, reason: '压力偏高 (使用率 80-100%)' };\n if (ratio < 1.2) return { score: 30, weight, reason: '压力超限 (100-120%)' };\n return { score: 0, weight, reason: '压力严重超限 (>120%)' };\n}\n\nfunction scoreProtection(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['protection'] {\n if (input.hasCathodicProtection === true) {\n return { score: 90, weight, reason: '有阴极保护' };\n }\n if (input.hasCathodicProtection === false) {\n return { score: 30, weight, reason: '无阴极保护' };\n }\n return { score: 50, weight, reason: '阴保状态未知' };\n}\n\n/**\n * 批量评分(按需遍历)\n */\nexport function scorePipes(inputs: PipeHealthInput[], weights = DEFAULT_WEIGHTS): PipeHealthScore[] {\n return inputs.map((i) => scorePipeHealth(i, weights));\n}\n","/**\n * 风险热力图(riskHeatmap)\n *\n * 把 scorePipeHealth 输出按地理网格聚合,输出每个网格的平均分/最高风险,\n * 用于地图热力图(heat-map layer)。\n *\n * 输入:管线数组 [{ lng, lat, healthScore }]\n * 输出:GeoJSON FeatureCollection<Point>(含 healthScore 属性)\n */\n\nexport interface HeatmapCell {\n lng: number;\n lat: number;\n healthScore: number;\n /** 网格内管段数 */\n pipeCount: number;\n}\n\nexport interface PipeHealthPoint {\n lng: number;\n lat: number;\n healthScore: number;\n}\n\nexport interface RiskHeatmapOptions {\n /** 网格尺寸(m),默认 500 */\n cellSize?: number;\n /** 聚合方式 */\n aggregation?: 'average' | 'min' | 'max';\n}\n\nexport function aggregateHeatmap(\n points: PipeHealthPoint[],\n options: RiskHeatmapOptions = {}\n): HeatmapCell[] {\n const cell = options.cellSize ?? 500;\n const agg = options.aggregation ?? 'average';\n\n // 经纬度 → 米近似(以第一个点为原点)\n if (points.length === 0) return [];\n\n const refLat = points[0].lat;\n const refLng = points[0].lng;\n const mPerDegLat = 110_540;\n const mPerDegLng = 111_320 * Math.cos((refLat * Math.PI) / 180);\n\n const grid = new Map<string, { acc: number; count: number; minS: number; maxS: number; lng: number; lat: number }>();\n for (const p of points) {\n const x = (p.lng - refLng) * mPerDegLng;\n const y = (p.lat - refLat) * mPerDegLat;\n const cx = Math.floor(x / cell);\n const cy = Math.floor(y / cell);\n const key = `${cx}:${cy}`;\n const cur = grid.get(key);\n if (!cur) {\n grid.set(key, {\n acc: p.healthScore,\n count: 1,\n minS: p.healthScore,\n maxS: p.healthScore,\n lng: p.lng,\n lat: p.lat,\n });\n } else {\n cur.acc += p.healthScore;\n cur.count += 1;\n if (p.healthScore < cur.minS) cur.minS = p.healthScore;\n if (p.healthScore > cur.maxS) cur.maxS = p.healthScore;\n cur.lng = (cur.lng * (cur.count - 1) + p.lng) / cur.count;\n cur.lat = (cur.lat * (cur.count - 1) + p.lat) / cur.count;\n }\n }\n\n const cells: HeatmapCell[] = [];\n for (const v of grid.values()) {\n let score: number;\n if (agg === 'min') score = v.minS;\n else if (agg === 'max') score = v.maxS;\n else score = v.acc / v.count;\n cells.push({\n lng: v.lng,\n lat: v.lat,\n healthScore: Math.round(score),\n pipeCount: v.count,\n });\n }\n return cells;\n}\n\nexport function heatmapToGeoJSON(cells: HeatmapCell[]): GeoJSON.FeatureCollection<GeoJSON.Point> {\n return {\n type: 'FeatureCollection',\n features: cells.map((c) => ({\n type: 'Feature',\n geometry: { type: 'Point', coordinates: [c.lng, c.lat] },\n properties: {\n healthScore: c.healthScore,\n pipeCount: c.pipeCount,\n },\n })),\n };\n}\n\n/** 优先维护建议列表(风险最高的 Top N 管线) */\nexport function prioritizeMaintenance(\n pipes: Array<{ id: string; healthScore: number; lng: number; lat: number; label?: string }>,\n topN = 10\n) {\n return [...pipes].sort((a, b) => a.healthScore - b.healthScore).slice(0, topN);\n}\n","/**\n * PipelineHealth 组件类(地图集成层)\n */\n\nimport type { Map as CaoguoMap } from '@caoguo/maplibre';\nimport { scorePipeHealth, type PipeHealthInput, type PipeHealthScore, DEFAULT_WEIGHTS } from './healthScorer';\nimport { aggregateHeatmap, heatmapToGeoJSON, type HeatmapCell, prioritizeMaintenance } from './riskHeatmap';\nimport type { PipelineTopologyDataset } from '../types';\n\nexport interface PipelineHealthOptions {\n map: CaoguoMap;\n dataset: PipelineTopologyDataset;\n cellSize?: number;\n layerPrefix?: string;\n}\n\nexport interface HealthResult {\n /** 全部管段评分 */\n scores: Array<{ pipeId: string; score: PipeHealthScore }>;\n /** 热力图聚合格 */\n heatmap: HeatmapCell[];\n /** 优先维护建议 */\n maintenance: Array<{ id: string; healthScore: number; lng: number; lat: number; label?: string }>;\n /** 计算耗时 */\n durationMs: number;\n}\n\ntype Listener = (r: HealthResult) => void;\n\n/**\n * 管线健康评估组件\n */\nexport class PipelineHealth {\n private map: CaoguoMap;\n private dataset: PipelineTopologyDataset;\n private cellSize: number;\n private layerPrefix: string;\n private listeners = new Set<Listener>();\n private lastResult: HealthResult | null = null;\n private layerIds: string[] = [];\n\n constructor(options: PipelineHealthOptions) {\n this.map = options.map;\n this.dataset = options.dataset;\n this.cellSize = options.cellSize ?? 500;\n this.layerPrefix = options.layerPrefix ?? 'cg-health';\n }\n\n /** 评估全网管线健康度 */\n evaluate(weights = DEFAULT_WEIGHTS): HealthResult {\n const t0 = (typeof performance !== 'undefined' ? performance.now() : Date.now());\n const nodeById = new Map(this.dataset.nodes.map((n) => [n.id, n] as const));\n\n const scores = this.dataset.pipes.map((p) => {\n const input: PipeHealthInput = {\n installDate: p.properties?.installDate,\n material: p.properties?.material,\n failureCount: undefined,\n pressure: p.properties?.pressure,\n ratedPressure: p.properties?.ratedPressure,\n hasCathodicProtection: undefined,\n status: p.properties?.status,\n };\n return { pipeId: p.id, score: scorePipeHealth(input, weights) };\n });\n\n const points = scores.flatMap((s, i) => {\n const pipe = this.dataset.pipes[i];\n const from = nodeById.get(pipe.fromNode);\n const to = nodeById.get(pipe.toNode);\n if (!from || !to) return [];\n return [\n {\n lng: (from.lng + to.lng) / 2,\n lat: (from.lat + to.lat) / 2,\n healthScore: s.score.score,\n },\n ];\n });\n\n const heatmap = aggregateHeatmap(points, { cellSize: this.cellSize });\n const maintenance = prioritizeMaintenance(\n scores.flatMap((s, i) => {\n const pipe = this.dataset.pipes[i];\n const from = nodeById.get(pipe.fromNode);\n const to = nodeById.get(pipe.toNode);\n if (!from || !to) return [];\n return [\n {\n id: pipe.id,\n healthScore: s.score.score,\n lng: (from.lng + to.lng) / 2,\n lat: (from.lat + to.lat) / 2,\n label: pipe.id,\n },\n ];\n })\n );\n\n const durationMs =\n (typeof performance !== 'undefined' ? performance.now() : Date.now()) - t0;\n\n const result: HealthResult = { scores, heatmap, maintenance, durationMs };\n this.lastResult = result;\n this.renderHeatmap(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(): HealthResult | null {\n return this.lastResult;\n }\n\n private renderHeatmap(result: HealthResult): void {\n this.clear();\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 const data = heatmapToGeoJSON(result.heatmap);\n const sourceId = `${this.layerPrefix}-heat-src`;\n const layerId = `${this.layerPrefix}-heat-point`;\n if (!mlMap.getSource(sourceId)) mlMap.addSource(sourceId, data);\n try {\n mlMap.addLayer({\n id: layerId,\n type: 'heatmap',\n source: sourceId,\n paint: {\n 'heatmap-weight': [\n 'interpolate',\n ['linear'],\n ['get', 'healthScore'],\n 0, 1,\n 50, 0.5,\n 100, 0,\n ] as unknown,\n 'heatmap-intensity': 1,\n 'heatmap-color': [\n 'interpolate',\n ['linear'],\n ['heatmap-density'],\n 0, 'rgba(34,197,94,0)',\n 0.2, 'rgba(34,197,94,0.5)',\n 0.5, 'rgba(245,158,11,0.7)',\n 0.8, 'rgba(239,68,68,0.8)',\n 1, 'rgba(127,29,29,0.9)',\n ] as unknown,\n 'heatmap-radius': 25,\n 'heatmap-opacity': 0.7,\n },\n });\n this.layerIds.push(layerId);\n } catch {\n // ignore\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/health/healthScorer.ts","../src/health/riskHeatmap.ts","../src/health/PipelineHealth.ts"],"names":[],"mappings":"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","file":"chunk-3656CGXE.js","sourcesContent":["/**\n * 管线健康度评分(healthScorer)\n *\n * 6 维加权评分(PRD §4.4.2):\n * health_score = age (0.25) + material (0.20) + soil (0.15) +\n * history (0.20) + pressure (0.10) + protection (0.10)\n *\n * 每维 0-100,最终加权求和。\n * 评分模型可解释:每个维度的评分依据清晰可见。\n */\n\nimport type { PipeMaterial, PipeStatus } from '../types';\n\nexport interface PipeHealthInput {\n /** 安装日期 ISO */\n installDate?: string;\n /** 材质 */\n material?: PipeMaterial;\n /** 当前故障次数 */\n failureCount?: number;\n /** 当前压力(MPa) */\n pressure?: number;\n /** 最高允许压力(MPa) */\n ratedPressure?: number;\n /** 是否阴极保护 */\n hasCathodicProtection?: boolean;\n /** 土壤腐蚀指数 0-1(无数据时 0.5) */\n soilCorrosion?: number;\n /** 状态(damaged / under_repair 直接影响评分) */\n status?: PipeStatus;\n}\n\nexport interface PipeHealthScore {\n /** 总分 0-100 */\n score: number;\n /** 等级 */\n level: 'excellent' | 'good' | 'fair' | 'poor' | 'critical';\n /** 6 维细分 */\n dimensions: {\n age: { score: number; weight: number; reason: string };\n material: { score: number; weight: number; reason: string };\n soil: { score: number; weight: number; reason: string };\n history: { score: number; weight: number; reason: string };\n pressure: { score: number; weight: number; reason: string };\n protection: { score: number; weight: number; reason: string };\n };\n}\n\n/** 默认权重 */\nexport const DEFAULT_WEIGHTS = {\n age: 0.25,\n material: 0.2,\n soil: 0.15,\n history: 0.2,\n pressure: 0.1,\n protection: 0.1,\n};\n\nconst MATERIAL_RISK: Record<PipeMaterial, number> = {\n cast_iron: 0.85, // 铸铁 = 高风险(旧管网)\n ductile_iron: 0.2, // 球墨铸铁\n steel: 0.4,\n pe: 0.1,\n pvc: 0.15,\n concrete: 0.3,\n hdpe: 0.05,\n copper: 0.1,\n unknown: 0.5,\n};\n\n/**\n * 计算单根管线的健康度\n */\nexport function scorePipeHealth(input: PipeHealthInput, weights = DEFAULT_WEIGHTS): PipeHealthScore {\n const dims = {\n age: scoreAge(input, weights.age),\n material: scoreMaterial(input, weights.material),\n soil: scoreSoil(input, weights.soil),\n history: scoreHistory(input, weights.history),\n pressure: scorePressure(input, weights.pressure),\n protection: scoreProtection(input, weights.protection),\n };\n\n const total =\n dims.age.score * dims.age.weight +\n dims.material.score * dims.material.weight +\n dims.soil.score * dims.soil.weight +\n dims.history.score * dims.history.weight +\n dims.pressure.score * dims.pressure.weight +\n dims.protection.score * dims.protection.weight;\n\n // 损坏或维修中额外惩罚\n let final = total;\n if (input.status === 'damaged') final *= 0.5;\n else if (input.status === 'under_repair') final *= 0.7;\n else if (input.status === 'abandoned') final = 0;\n\n return {\n score: Math.round(final),\n level: toLevel(final),\n dimensions: dims,\n };\n}\n\nfunction toLevel(score: number): PipeHealthScore['level'] {\n if (score >= 80) return 'excellent';\n if (score >= 60) return 'good';\n if (score >= 40) return 'fair';\n if (score >= 20) return 'poor';\n return 'critical';\n}\n\nfunction scoreAge(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['age'] {\n if (!input.installDate) {\n return { score: 50, weight, reason: '未知安装日期,按中等计' };\n }\n const ageYears = (Date.now() - new Date(input.installDate).getTime()) / (365.25 * 24 * 3600 * 1000);\n if (ageYears < 0) return { score: 100, weight, reason: '未来日期,视为优秀' };\n if (ageYears < 5) return { score: 100, weight, reason: '新建管线 (<5年)' };\n if (ageYears < 15) return { score: 85, weight, reason: '较新 (5-15年)' };\n if (ageYears < 25) return { score: 65, weight, reason: '中龄 (15-25年)' };\n if (ageYears < 40) return { score: 40, weight, reason: '老龄 (25-40年)' };\n if (ageYears < 60) return { score: 20, weight, reason: '超期 (>40年)' };\n return { score: 5, weight, reason: '超期 (>60年)' };\n}\n\nfunction scoreMaterial(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['material'] {\n if (!input.material) {\n return { score: 50, weight, reason: '未知材质,按中等计' };\n }\n const risk = MATERIAL_RISK[input.material] ?? 0.5;\n const score = Math.round((1 - risk) * 100);\n const labels: Record<string, string> = {\n cast_iron: '铸铁(高风险)',\n ductile_iron: '球墨铸铁',\n steel: '钢',\n pe: 'PE(低风险)',\n pvc: 'PVC',\n concrete: '混凝土',\n hdpe: 'HDPE(最佳)',\n copper: '铜',\n unknown: '未知',\n };\n return {\n score,\n weight,\n reason: labels[input.material] ?? input.material,\n };\n}\n\nfunction scoreSoil(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['soil'] {\n const c = input.soilCorrosion ?? 0.5;\n const score = Math.round((1 - c) * 100);\n return {\n score,\n weight,\n reason: c === 0.5 && !input.soilCorrosion ? '无土壤数据,按平均计' : `土壤腐蚀指数 ${c.toFixed(2)}`,\n };\n}\n\nfunction scoreHistory(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['history'] {\n const fail = input.failureCount ?? 0;\n if (fail === 0) return { score: 100, weight, reason: '历史无故障' };\n if (fail === 1) return { score: 75, weight, reason: '历史 1 次故障' };\n if (fail === 2) return { score: 50, weight, reason: '历史 2 次故障' };\n if (fail === 3) return { score: 25, weight, reason: '历史 3 次故障' };\n return { score: 0, weight, reason: `历史 ≥${fail} 次故障` };\n}\n\nfunction scorePressure(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['pressure'] {\n if (!input.pressure) {\n return { score: 75, weight, reason: '无压力数据,按中等偏好计' };\n }\n if (!input.ratedPressure) {\n return { score: 75, weight, reason: '仅知当前压力' };\n }\n const ratio = input.pressure / input.ratedPressure;\n if (ratio < 0.5) return { score: 60, weight, reason: '压力偏低 (使用率 <50%)' };\n if (ratio < 0.8) return { score: 90, weight, reason: '压力正常 (使用率 50-80%)' };\n if (ratio < 1.0) return { score: 75, weight, reason: '压力偏高 (使用率 80-100%)' };\n if (ratio < 1.2) return { score: 30, weight, reason: '压力超限 (100-120%)' };\n return { score: 0, weight, reason: '压力严重超限 (>120%)' };\n}\n\nfunction scoreProtection(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['protection'] {\n if (input.hasCathodicProtection === true) {\n return { score: 90, weight, reason: '有阴极保护' };\n }\n if (input.hasCathodicProtection === false) {\n return { score: 30, weight, reason: '无阴极保护' };\n }\n return { score: 50, weight, reason: '阴保状态未知' };\n}\n\n/**\n * 批量评分(按需遍历)\n */\nexport function scorePipes(inputs: PipeHealthInput[], weights = DEFAULT_WEIGHTS): PipeHealthScore[] {\n return inputs.map((i) => scorePipeHealth(i, weights));\n}\n","/**\n * 风险热力图(riskHeatmap)\n *\n * 把 scorePipeHealth 输出按地理网格聚合,输出每个网格的平均分/最高风险,\n * 用于地图热力图(heat-map layer)。\n *\n * 输入:管线数组 [{ lng, lat, healthScore }]\n * 输出:GeoJSON FeatureCollection<Point>(含 healthScore 属性)\n */\n\nexport interface HeatmapCell {\n lng: number;\n lat: number;\n healthScore: number;\n /** 网格内管段数 */\n pipeCount: number;\n}\n\nexport interface PipeHealthPoint {\n lng: number;\n lat: number;\n healthScore: number;\n}\n\nexport interface RiskHeatmapOptions {\n /** 网格尺寸(m),默认 500 */\n cellSize?: number;\n /** 聚合方式 */\n aggregation?: 'average' | 'min' | 'max';\n}\n\nexport function aggregateHeatmap(\n points: PipeHealthPoint[],\n options: RiskHeatmapOptions = {}\n): HeatmapCell[] {\n const cell = options.cellSize ?? 500;\n const agg = options.aggregation ?? 'average';\n\n // 经纬度 → 米近似(以第一个点为原点)\n if (points.length === 0) return [];\n\n const refLat = points[0].lat;\n const refLng = points[0].lng;\n const mPerDegLat = 110_540;\n const mPerDegLng = 111_320 * Math.cos((refLat * Math.PI) / 180);\n\n const grid = new Map<string, { acc: number; count: number; minS: number; maxS: number; lng: number; lat: number }>();\n for (const p of points) {\n const x = (p.lng - refLng) * mPerDegLng;\n const y = (p.lat - refLat) * mPerDegLat;\n const cx = Math.floor(x / cell);\n const cy = Math.floor(y / cell);\n const key = `${cx}:${cy}`;\n const cur = grid.get(key);\n if (!cur) {\n grid.set(key, {\n acc: p.healthScore,\n count: 1,\n minS: p.healthScore,\n maxS: p.healthScore,\n lng: p.lng,\n lat: p.lat,\n });\n } else {\n cur.acc += p.healthScore;\n cur.count += 1;\n if (p.healthScore < cur.minS) cur.minS = p.healthScore;\n if (p.healthScore > cur.maxS) cur.maxS = p.healthScore;\n cur.lng = (cur.lng * (cur.count - 1) + p.lng) / cur.count;\n cur.lat = (cur.lat * (cur.count - 1) + p.lat) / cur.count;\n }\n }\n\n const cells: HeatmapCell[] = [];\n for (const v of grid.values()) {\n let score: number;\n if (agg === 'min') score = v.minS;\n else if (agg === 'max') score = v.maxS;\n else score = v.acc / v.count;\n cells.push({\n lng: v.lng,\n lat: v.lat,\n healthScore: Math.round(score),\n pipeCount: v.count,\n });\n }\n return cells;\n}\n\nexport function heatmapToGeoJSON(cells: HeatmapCell[]): GeoJSON.FeatureCollection<GeoJSON.Point> {\n return {\n type: 'FeatureCollection',\n features: cells.map((c) => ({\n type: 'Feature',\n geometry: { type: 'Point', coordinates: [c.lng, c.lat] },\n properties: {\n healthScore: c.healthScore,\n pipeCount: c.pipeCount,\n },\n })),\n };\n}\n\n/** 优先维护建议列表(风险最高的 Top N 管线) */\nexport function prioritizeMaintenance(\n pipes: Array<{ id: string; healthScore: number; lng: number; lat: number; label?: string }>,\n topN = 10\n) {\n return [...pipes].sort((a, b) => a.healthScore - b.healthScore).slice(0, topN);\n}\n","/**\n * PipelineHealth 组件类(地图集成层)\n */\n\nimport type { Map as CaoguoMap } from '@caoguo/maplibre';\nimport { scorePipeHealth, type PipeHealthInput, type PipeHealthScore, DEFAULT_WEIGHTS } from './healthScorer';\nimport { aggregateHeatmap, heatmapToGeoJSON, type HeatmapCell, prioritizeMaintenance } from './riskHeatmap';\nimport type { PipelineTopologyDataset } from '../types';\n\nexport interface PipelineHealthOptions {\n map: CaoguoMap;\n dataset: PipelineTopologyDataset;\n cellSize?: number;\n layerPrefix?: string;\n}\n\nexport interface HealthResult {\n /** 全部管段评分 */\n scores: Array<{ pipeId: string; score: PipeHealthScore }>;\n /** 热力图聚合格 */\n heatmap: HeatmapCell[];\n /** 优先维护建议 */\n maintenance: Array<{ id: string; healthScore: number; lng: number; lat: number; label?: string }>;\n /** 计算耗时 */\n durationMs: number;\n}\n\ntype Listener = (r: HealthResult) => void;\n\n/**\n * 管线健康评估组件\n */\nexport class PipelineHealth {\n private map: CaoguoMap;\n private dataset: PipelineTopologyDataset;\n private cellSize: number;\n private layerPrefix: string;\n private listeners = new Set<Listener>();\n private lastResult: HealthResult | null = null;\n private layerIds: string[] = [];\n\n constructor(options: PipelineHealthOptions) {\n this.map = options.map;\n this.dataset = options.dataset;\n this.cellSize = options.cellSize ?? 500;\n this.layerPrefix = options.layerPrefix ?? 'cg-health';\n }\n\n /** 评估全网管线健康度 */\n evaluate(weights = DEFAULT_WEIGHTS): HealthResult {\n const t0 = (typeof performance !== 'undefined' ? performance.now() : Date.now());\n const nodeById = new Map(this.dataset.nodes.map((n) => [n.id, n] as const));\n\n const scores = this.dataset.pipes.map((p) => {\n const input: PipeHealthInput = {\n installDate: p.properties?.installDate,\n material: p.properties?.material,\n failureCount: p.properties?.failureCount ?? 0,\n pressure: p.properties?.pressure,\n ratedPressure: p.properties?.ratedPressure,\n hasCathodicProtection: p.properties?.hasCathodicProtection ?? false,\n status: p.properties?.status,\n };\n return { pipeId: p.id, score: scorePipeHealth(input, weights) };\n });\n\n const points = scores.flatMap((s, i) => {\n const pipe = this.dataset.pipes[i];\n const from = nodeById.get(pipe.fromNode);\n const to = nodeById.get(pipe.toNode);\n if (!from || !to) return [];\n return [\n {\n lng: (from.lng + to.lng) / 2,\n lat: (from.lat + to.lat) / 2,\n healthScore: s.score.score,\n },\n ];\n });\n\n const heatmap = aggregateHeatmap(points, { cellSize: this.cellSize });\n const maintenance = prioritizeMaintenance(\n scores.flatMap((s, i) => {\n const pipe = this.dataset.pipes[i];\n const from = nodeById.get(pipe.fromNode);\n const to = nodeById.get(pipe.toNode);\n if (!from || !to) return [];\n return [\n {\n id: pipe.id,\n healthScore: s.score.score,\n lng: (from.lng + to.lng) / 2,\n lat: (from.lat + to.lat) / 2,\n label: pipe.id,\n },\n ];\n })\n );\n\n const durationMs =\n (typeof performance !== 'undefined' ? performance.now() : Date.now()) - t0;\n\n const result: HealthResult = { scores, heatmap, maintenance, durationMs };\n this.lastResult = result;\n this.renderHeatmap(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(): HealthResult | null {\n return this.lastResult;\n }\n\n private renderHeatmap(result: HealthResult): void {\n this.clear();\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 const data = heatmapToGeoJSON(result.heatmap);\n const sourceId = `${this.layerPrefix}-heat-src`;\n const layerId = `${this.layerPrefix}-heat-point`;\n if (!mlMap.getSource(sourceId)) mlMap.addSource(sourceId, data);\n try {\n mlMap.addLayer({\n id: layerId,\n type: 'heatmap',\n source: sourceId,\n paint: {\n 'heatmap-weight': [\n 'interpolate',\n ['linear'],\n ['get', 'healthScore'],\n 0, 1,\n 50, 0.5,\n 100, 0,\n ] as unknown,\n 'heatmap-intensity': 1,\n 'heatmap-color': [\n 'interpolate',\n ['linear'],\n ['heatmap-density'],\n 0, 'rgba(34,197,94,0)',\n 0.2, 'rgba(34,197,94,0.5)',\n 0.5, 'rgba(245,158,11,0.7)',\n 0.8, 'rgba(239,68,68,0.8)',\n 1, 'rgba(127,29,29,0.9)',\n ] as unknown,\n 'heatmap-radius': 25,\n 'heatmap-opacity': 0.7,\n },\n });\n this.layerIds.push(layerId);\n } catch {\n // ignore\n }\n }\n}\n"]}
@@ -9,5 +9,5 @@ var PIPELINE_TYPES = [
9
9
  ];
10
10
 
11
11
  export { PIPELINE_TYPES };
12
- //# sourceMappingURL=chunk-HIRNJVCV.js.map
13
- //# sourceMappingURL=chunk-HIRNJVCV.js.map
12
+ //# sourceMappingURL=chunk-E4BRNDKY.js.map
13
+ //# sourceMappingURL=chunk-E4BRNDKY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types/index.ts"],"names":[],"mappings":";AA0BO,IAAM,cAAA,GAA0C;AAAA,EACrD,KAAA;AAAA,EACA,OAAA;AAAA,EACA,UAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF","file":"chunk-E4BRNDKY.js","sourcesContent":["/**\n * 草果地图管网组件包 - 类型定义\n *\n * 地下管网 MVP 数据模型:\n * - 节点(Node):管段的交汇点/设备点(阀门/泵/表/源头)\n * - 管段(Pipe/Edge):连接两个节点的物理管线\n * - 用户(User):连接到节点的消费方(居民/商业/工业)\n *\n * 拓扑数据结构参见 PRD phase-1-pipeline §4.1.2\n */\n\n// ============================================================\n// 一、管线类型(基础设施大类)\n// ============================================================\n/**\n * 管网大类\n * - gas:燃气\n * - water:供水\n * - drainage:排水\n * - heating:供热\n * - power:电力(管沟)\n * - telecom:通信(管沟)\n */\nexport type PipelineType = 'gas' | 'water' | 'drainage' | 'heating' | 'power' | 'telecom';\n\n/** 所有支持的管线大类(便于运行时校验) */\nexport const PIPELINE_TYPES: readonly PipelineType[] = [\n 'gas',\n 'water',\n 'drainage',\n 'heating',\n 'power',\n 'telecom',\n] as const;\n\n// ============================================================\n// 二、节点(Node)\n// ============================================================\n/**\n * 节点类型\n * - junction:普通连接点(三通/四通/弯头等)\n * - valve:阀门(可关闭以隔离故障段)\n * - pump:泵站(供水加压/供热循环)\n * - meter:计量表/用户表\n * - source:源头(制水厂/燃气门站/热源厂)\n * - tank:储水罐/储气罐\n * - junction_box:电缆/光缆接线井\n */\nexport type NodeKind =\n | 'junction'\n | 'valve'\n | 'pump'\n | 'meter'\n | 'source'\n | 'tank'\n | 'junction_box';\n\n/** 阀门子类型 */\nexport type ValveType = 'gate' | 'butterfly' | 'check' | 'pressure_reduction' | 'control';\n\n/** 阀门状态(用于爆管推演隔离方案) */\nexport type ValveStatus = 'open' | 'closed' | 'partial';\n\n// ============================================================\n// 三、管段(Pipe/Edge)\n// ============================================================\n/**\n * 管段材质\n * - cast_iron:铸铁(旧管网主力)\n * - ductile_iron:球墨铸铁(当前主流)\n * - steel:钢管(高压/燃气主干)\n * - pe:聚乙烯(PE,现代供水/燃气)\n * - pvc:聚氯乙烯(PVC,排水)\n * - concrete:混凝土(排水/给水主干)\n * - hdpe:高密度聚乙烯\n * - copper:铜管(室内引入管)\n * - unknown:未知\n */\nexport type PipeMaterial =\n | 'cast_iron'\n | 'ductile_iron'\n | 'steel'\n | 'pe'\n | 'pvc'\n | 'concrete'\n | 'hdpe'\n | 'copper'\n | 'unknown';\n\n/**\n * 管段状态\n * - normal:正常运行\n * - aging:老化(建议关注)\n * - damaged:损坏(泄漏/破裂)\n * - under_repair:维修中(部分阀门/路段暂停使用)\n * - abandoned:废弃\n * - unknown:未知\n */\nexport type PipeStatus =\n | 'normal'\n | 'aging'\n | 'damaged'\n | 'under_repair'\n | 'abandoned'\n | 'unknown';\n\n// ============================================================\n// 四、设备附加属性(管段 / 节点公用扩展)\n// ============================================================\nexport interface PipeProperties {\n /** 公称直径(mm),如 DN150 = 150 */\n diameter?: number;\n /** 管材 */\n material?: PipeMaterial;\n /** 安装日期(ISO 字符串) */\n installDate?: string;\n /** 工作压力(MPa) */\n pressure?: number;\n /** 最高允许压力(MPa) */\n ratedPressure?: number;\n /** 历史故障次数(健康评分 history 维,PRD §4.4.2) */\n failureCount?: number;\n /** 是否阴极保护(健康评分 protection 维,PRD §4.4.2) */\n hasCathodicProtection?: boolean;\n /** 当前状态 */\n status?: PipeStatus;\n /** 埋深(m) */\n depth?: number;\n /** 建设单位 */\n owner?: string;\n /** 自由扩展(运维记录/检测报告 URL 等) */\n extra?: Record<string, unknown>;\n}\n\nexport interface NodeProperties {\n /** 设备编号 */\n code?: string;\n /** 阀门类型(仅 valve) */\n valveType?: ValveType;\n /** 阀门状态(仅 valve) */\n valveStatus?: ValveStatus;\n /** 流量/供气能力(m³/h,仅 source/pump) */\n capacity?: number;\n /** 安装日期 */\n installDate?: string;\n /** 产权单位 */\n owner?: string;\n /** 海拔(m,用于地形修正) */\n elevation?: number;\n /** 自由扩展 */\n extra?: Record<string, unknown>;\n}\n\n// ============================================================\n// 五、节点(Node)\n// ============================================================\n/**\n * 管网节点\n * position 为 [lng, lat](GeoJSON 习惯),不是 [lat, lng]\n */\nexport interface PipelineNode {\n id: string;\n /** 节点类型 */\n kind: NodeKind;\n /** 经度(WGS84) */\n lng: number;\n /** 纬度(WGS84) */\n lat: number;\n /** 所属管线大类(燃气/供水等) */\n pipelineType?: PipelineType;\n /** 行政区/区域(用于层级钻取) */\n region?: string;\n /** 自定义属性 */\n properties?: NodeProperties;\n}\n\n// ============================================================\n// 六、管段(Pipe/Edge)\n// ============================================================\n/**\n * 管网管段\n * from_node / to_node 是有向连接,但物理上双向导通。\n * 地理 LineString 用 [[lng,lat], ...] 表示。\n */\nexport interface PipelinePipe {\n id: string;\n /** 起点节点 id */\n fromNode: string;\n /** 终点节点 id */\n toNode: string;\n /** 管段类型,固定为 'pipe'(预留扩展如 'channel'/'duct') */\n type: 'pipe';\n /** 所属管线大类 */\n pipelineType?: PipelineType;\n /** 区域编码(用于 LOD 按需加载) */\n region?: string;\n /** 几何(可选,未提供时按 from/to 拉直线) */\n geometry?: [number, number][];\n /** 长度(m),可选,由 geometry 计算 */\n length?: number;\n /** 管段属性 */\n properties?: PipeProperties;\n}\n\n// ============================================================\n// 七、用户/建筑(爆管推演影响分析用)\n// ============================================================\n/**\n * 用户类型\n * - residential:居民\n * - commercial:商业\n * - industrial:工业\n * - important:重要用户(医院/学校/政府部门/消防)\n */\nexport type UserKind = 'residential' | 'commercial' | 'industrial' | 'important';\n\nexport interface PipelineUser {\n id: string;\n /** 用户名 */\n name?: string;\n /** 类型 */\n kind: UserKind;\n /** 所属节点 id(直接或间接连接) */\n nodeId?: string;\n /** 位置 */\n lng: number;\n lat: number;\n /** 区域 */\n region?: string;\n /** 人口/用量(可选) */\n scale?: number;\n /** 备注 */\n note?: string;\n}\n\n// ============================================================\n// 八、完整管网拓扑\n// ============================================================\n/**\n * 管网拓扑数据集(完整 MVP 输入)\n * - nodes:节点列表\n * - pipes:管段列表\n * - users:用户列表(可选,爆管推演需要)\n */\nexport interface PipelineTopologyDataset {\n nodes: PipelineNode[];\n pipes: PipelinePipe[];\n users?: PipelineUser[];\n}\n\n// ============================================================\n// 九、事件载荷(包内统一事件类型)\n// ============================================================\n/** 选中节点 */\nexport interface NodeSelectEvent {\n node: PipelineNode;\n /** 在鼠标事件中的屏幕坐标(可选) */\n point?: { x: number; y: number };\n}\n\n/** 选中管段 */\nexport interface PipeSelectEvent {\n pipe: PipelinePipe;\n point?: { x: number; y: number };\n}\n\n/** 钻取事件(区域层级下钻) */\nexport interface DrillDownEvent {\n /** 上一级区域 */\n from: string | null;\n /** 目标区域 */\n to: string;\n}\n\n// ============================================================\n// 十、可视化着色规则(caoguo-pipeline 主题)\n// ============================================================\n/**\n * 着色模式(管线渲染)\n * - type:按管线大类着色(燃气黄/供水蓝等)\n * - diameter:按管径着色(PRD §4.1.4)\n * - status:按管段状态着色\n * - material:按管材着色\n * - health:按健康度着色(PipelineHealth 集成)\n * - uniform:单一颜色\n */\nexport type ColorByMode =\n | 'type'\n | 'diameter'\n | 'status'\n | 'material'\n | 'health'\n | 'uniform';\n"]}
@@ -348,5 +348,5 @@ var LeakagePlume = class {
348
348
  };
349
349
 
350
350
  export { LeakagePlume, classifyFromMeteo, classifyStability, dispersionCoefficients, gaussianPlume, simulateFlood };
351
- //# sourceMappingURL=chunk-PJMHTPSA.js.map
352
- //# sourceMappingURL=chunk-PJMHTPSA.js.map
351
+ //# sourceMappingURL=chunk-VSTG2ZUY.js.map
352
+ //# sourceMappingURL=chunk-VSTG2ZUY.js.map
@@ -1 +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":"chunk-PJMHTPSA.js","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 { upsertSource } 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 upsertSource(mlMap, 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 upsertSource(mlMap, 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 // 标记泄漏点(幂等:模拟重渲染时 source 可能已存在)\n const ptId = `${this.layerPrefix}-source`;\n const ptData = {\n type: 'FeatureCollection' as const,\n features: [\n {\n type: 'Feature' as const,\n geometry: { type: 'Point' as const, coordinates: [source.lng, source.lat] },\n properties: {},\n },\n ],\n };\n upsertSource(mlMap, ptId, ptData);\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"]}
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":"chunk-VSTG2ZUY.js","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 组件类(地图集成层)\n *\n * 包装高斯烟羽扩散(gaussianPlume)与淹没范围(simulateFlood)纯函数,\n * 维护 MapLibre 图层状态,对外暴露浓度云图 / 淹没范围渲染 API。\n * 不依赖 Vue/React,可在任意框架实例化。\n */\n\nimport type { Map as CaoguoMap } from '@caoguo/maplibre';\nimport { upsertSource } 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 upsertSource(mlMap, 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 upsertSource(mlMap, 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 // 标记泄漏点(幂等:模拟重渲染时 source 可能已存在)\n const ptId = `${this.layerPrefix}-source`;\n const ptData = {\n type: 'FeatureCollection' as const,\n features: [\n {\n type: 'Feature' as const,\n geometry: { type: 'Point' as const, coordinates: [source.lng, source.lat] },\n properties: {},\n },\n ],\n };\n upsertSource(mlMap, ptId, ptData);\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"]}
@@ -219,10 +219,10 @@ var PipelineHealth = class {
219
219
  const input = {
220
220
  installDate: p.properties?.installDate,
221
221
  material: p.properties?.material,
222
- failureCount: void 0,
222
+ failureCount: p.properties?.failureCount ?? 0,
223
223
  pressure: p.properties?.pressure,
224
224
  ratedPressure: p.properties?.ratedPressure,
225
- hasCathodicProtection: void 0,
225
+ hasCathodicProtection: p.properties?.hasCathodicProtection ?? false,
226
226
  status: p.properties?.status
227
227
  };
228
228
  return { pipeId: p.id, score: scorePipeHealth(input, weights) };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/health/healthScorer.ts","../../src/health/riskHeatmap.ts","../../src/health/PipelineHealth.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * 管线健康度评分(healthScorer)\n *\n * 6 维加权评分(PRD §4.4.2):\n * health_score = age (0.25) + material (0.20) + soil (0.15) +\n * history (0.20) + pressure (0.10) + protection (0.10)\n *\n * 每维 0-100,最终加权求和。\n * 评分模型可解释:每个维度的评分依据清晰可见。\n */\n\nimport type { PipeMaterial, PipeStatus } from '../types';\n\nexport interface PipeHealthInput {\n /** 安装日期 ISO */\n installDate?: string;\n /** 材质 */\n material?: PipeMaterial;\n /** 当前故障次数 */\n failureCount?: number;\n /** 当前压力(MPa) */\n pressure?: number;\n /** 最高允许压力(MPa) */\n ratedPressure?: number;\n /** 是否阴极保护 */\n hasCathodicProtection?: boolean;\n /** 土壤腐蚀指数 0-1(无数据时 0.5) */\n soilCorrosion?: number;\n /** 状态(damaged / under_repair 直接影响评分) */\n status?: PipeStatus;\n}\n\nexport interface PipeHealthScore {\n /** 总分 0-100 */\n score: number;\n /** 等级 */\n level: 'excellent' | 'good' | 'fair' | 'poor' | 'critical';\n /** 6 维细分 */\n dimensions: {\n age: { score: number; weight: number; reason: string };\n material: { score: number; weight: number; reason: string };\n soil: { score: number; weight: number; reason: string };\n history: { score: number; weight: number; reason: string };\n pressure: { score: number; weight: number; reason: string };\n protection: { score: number; weight: number; reason: string };\n };\n}\n\n/** 默认权重 */\nexport const DEFAULT_WEIGHTS = {\n age: 0.25,\n material: 0.2,\n soil: 0.15,\n history: 0.2,\n pressure: 0.1,\n protection: 0.1,\n};\n\nconst MATERIAL_RISK: Record<PipeMaterial, number> = {\n cast_iron: 0.85, // 铸铁 = 高风险(旧管网)\n ductile_iron: 0.2, // 球墨铸铁\n steel: 0.4,\n pe: 0.1,\n pvc: 0.15,\n concrete: 0.3,\n hdpe: 0.05,\n copper: 0.1,\n unknown: 0.5,\n};\n\n/**\n * 计算单根管线的健康度\n */\nexport function scorePipeHealth(input: PipeHealthInput, weights = DEFAULT_WEIGHTS): PipeHealthScore {\n const dims = {\n age: scoreAge(input, weights.age),\n material: scoreMaterial(input, weights.material),\n soil: scoreSoil(input, weights.soil),\n history: scoreHistory(input, weights.history),\n pressure: scorePressure(input, weights.pressure),\n protection: scoreProtection(input, weights.protection),\n };\n\n const total =\n dims.age.score * dims.age.weight +\n dims.material.score * dims.material.weight +\n dims.soil.score * dims.soil.weight +\n dims.history.score * dims.history.weight +\n dims.pressure.score * dims.pressure.weight +\n dims.protection.score * dims.protection.weight;\n\n // 损坏或维修中额外惩罚\n let final = total;\n if (input.status === 'damaged') final *= 0.5;\n else if (input.status === 'under_repair') final *= 0.7;\n else if (input.status === 'abandoned') final = 0;\n\n return {\n score: Math.round(final),\n level: toLevel(final),\n dimensions: dims,\n };\n}\n\nfunction toLevel(score: number): PipeHealthScore['level'] {\n if (score >= 80) return 'excellent';\n if (score >= 60) return 'good';\n if (score >= 40) return 'fair';\n if (score >= 20) return 'poor';\n return 'critical';\n}\n\nfunction scoreAge(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['age'] {\n if (!input.installDate) {\n return { score: 50, weight, reason: '未知安装日期,按中等计' };\n }\n const ageYears = (Date.now() - new Date(input.installDate).getTime()) / (365.25 * 24 * 3600 * 1000);\n if (ageYears < 0) return { score: 100, weight, reason: '未来日期,视为优秀' };\n if (ageYears < 5) return { score: 100, weight, reason: '新建管线 (<5年)' };\n if (ageYears < 15) return { score: 85, weight, reason: '较新 (5-15年)' };\n if (ageYears < 25) return { score: 65, weight, reason: '中龄 (15-25年)' };\n if (ageYears < 40) return { score: 40, weight, reason: '老龄 (25-40年)' };\n if (ageYears < 60) return { score: 20, weight, reason: '超期 (>40年)' };\n return { score: 5, weight, reason: '超期 (>60年)' };\n}\n\nfunction scoreMaterial(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['material'] {\n if (!input.material) {\n return { score: 50, weight, reason: '未知材质,按中等计' };\n }\n const risk = MATERIAL_RISK[input.material] ?? 0.5;\n const score = Math.round((1 - risk) * 100);\n const labels: Record<string, string> = {\n cast_iron: '铸铁(高风险)',\n ductile_iron: '球墨铸铁',\n steel: '钢',\n pe: 'PE(低风险)',\n pvc: 'PVC',\n concrete: '混凝土',\n hdpe: 'HDPE(最佳)',\n copper: '铜',\n unknown: '未知',\n };\n return {\n score,\n weight,\n reason: labels[input.material] ?? input.material,\n };\n}\n\nfunction scoreSoil(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['soil'] {\n const c = input.soilCorrosion ?? 0.5;\n const score = Math.round((1 - c) * 100);\n return {\n score,\n weight,\n reason: c === 0.5 && !input.soilCorrosion ? '无土壤数据,按平均计' : `土壤腐蚀指数 ${c.toFixed(2)}`,\n };\n}\n\nfunction scoreHistory(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['history'] {\n const fail = input.failureCount ?? 0;\n if (fail === 0) return { score: 100, weight, reason: '历史无故障' };\n if (fail === 1) return { score: 75, weight, reason: '历史 1 次故障' };\n if (fail === 2) return { score: 50, weight, reason: '历史 2 次故障' };\n if (fail === 3) return { score: 25, weight, reason: '历史 3 次故障' };\n return { score: 0, weight, reason: `历史 ≥${fail} 次故障` };\n}\n\nfunction scorePressure(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['pressure'] {\n if (!input.pressure) {\n return { score: 75, weight, reason: '无压力数据,按中等偏好计' };\n }\n if (!input.ratedPressure) {\n return { score: 75, weight, reason: '仅知当前压力' };\n }\n const ratio = input.pressure / input.ratedPressure;\n if (ratio < 0.5) return { score: 60, weight, reason: '压力偏低 (使用率 <50%)' };\n if (ratio < 0.8) return { score: 90, weight, reason: '压力正常 (使用率 50-80%)' };\n if (ratio < 1.0) return { score: 75, weight, reason: '压力偏高 (使用率 80-100%)' };\n if (ratio < 1.2) return { score: 30, weight, reason: '压力超限 (100-120%)' };\n return { score: 0, weight, reason: '压力严重超限 (>120%)' };\n}\n\nfunction scoreProtection(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['protection'] {\n if (input.hasCathodicProtection === true) {\n return { score: 90, weight, reason: '有阴极保护' };\n }\n if (input.hasCathodicProtection === false) {\n return { score: 30, weight, reason: '无阴极保护' };\n }\n return { score: 50, weight, reason: '阴保状态未知' };\n}\n\n/**\n * 批量评分(按需遍历)\n */\nexport function scorePipes(inputs: PipeHealthInput[], weights = DEFAULT_WEIGHTS): PipeHealthScore[] {\n return inputs.map((i) => scorePipeHealth(i, weights));\n}\n","/**\n * 风险热力图(riskHeatmap)\n *\n * 把 scorePipeHealth 输出按地理网格聚合,输出每个网格的平均分/最高风险,\n * 用于地图热力图(heat-map layer)。\n *\n * 输入:管线数组 [{ lng, lat, healthScore }]\n * 输出:GeoJSON FeatureCollection<Point>(含 healthScore 属性)\n */\n\nexport interface HeatmapCell {\n lng: number;\n lat: number;\n healthScore: number;\n /** 网格内管段数 */\n pipeCount: number;\n}\n\nexport interface PipeHealthPoint {\n lng: number;\n lat: number;\n healthScore: number;\n}\n\nexport interface RiskHeatmapOptions {\n /** 网格尺寸(m),默认 500 */\n cellSize?: number;\n /** 聚合方式 */\n aggregation?: 'average' | 'min' | 'max';\n}\n\nexport function aggregateHeatmap(\n points: PipeHealthPoint[],\n options: RiskHeatmapOptions = {}\n): HeatmapCell[] {\n const cell = options.cellSize ?? 500;\n const agg = options.aggregation ?? 'average';\n\n // 经纬度 → 米近似(以第一个点为原点)\n if (points.length === 0) return [];\n\n const refLat = points[0].lat;\n const refLng = points[0].lng;\n const mPerDegLat = 110_540;\n const mPerDegLng = 111_320 * Math.cos((refLat * Math.PI) / 180);\n\n const grid = new Map<string, { acc: number; count: number; minS: number; maxS: number; lng: number; lat: number }>();\n for (const p of points) {\n const x = (p.lng - refLng) * mPerDegLng;\n const y = (p.lat - refLat) * mPerDegLat;\n const cx = Math.floor(x / cell);\n const cy = Math.floor(y / cell);\n const key = `${cx}:${cy}`;\n const cur = grid.get(key);\n if (!cur) {\n grid.set(key, {\n acc: p.healthScore,\n count: 1,\n minS: p.healthScore,\n maxS: p.healthScore,\n lng: p.lng,\n lat: p.lat,\n });\n } else {\n cur.acc += p.healthScore;\n cur.count += 1;\n if (p.healthScore < cur.minS) cur.minS = p.healthScore;\n if (p.healthScore > cur.maxS) cur.maxS = p.healthScore;\n cur.lng = (cur.lng * (cur.count - 1) + p.lng) / cur.count;\n cur.lat = (cur.lat * (cur.count - 1) + p.lat) / cur.count;\n }\n }\n\n const cells: HeatmapCell[] = [];\n for (const v of grid.values()) {\n let score: number;\n if (agg === 'min') score = v.minS;\n else if (agg === 'max') score = v.maxS;\n else score = v.acc / v.count;\n cells.push({\n lng: v.lng,\n lat: v.lat,\n healthScore: Math.round(score),\n pipeCount: v.count,\n });\n }\n return cells;\n}\n\nexport function heatmapToGeoJSON(cells: HeatmapCell[]): GeoJSON.FeatureCollection<GeoJSON.Point> {\n return {\n type: 'FeatureCollection',\n features: cells.map((c) => ({\n type: 'Feature',\n geometry: { type: 'Point', coordinates: [c.lng, c.lat] },\n properties: {\n healthScore: c.healthScore,\n pipeCount: c.pipeCount,\n },\n })),\n };\n}\n\n/** 优先维护建议列表(风险最高的 Top N 管线) */\nexport function prioritizeMaintenance(\n pipes: Array<{ id: string; healthScore: number; lng: number; lat: number; label?: string }>,\n topN = 10\n) {\n return [...pipes].sort((a, b) => a.healthScore - b.healthScore).slice(0, topN);\n}\n","/**\n * PipelineHealth 组件类(地图集成层)\n */\n\nimport type { Map as CaoguoMap } from '@caoguo/maplibre';\nimport { scorePipeHealth, type PipeHealthInput, type PipeHealthScore, DEFAULT_WEIGHTS } from './healthScorer';\nimport { aggregateHeatmap, heatmapToGeoJSON, type HeatmapCell, prioritizeMaintenance } from './riskHeatmap';\nimport type { PipelineTopologyDataset } from '../types';\n\nexport interface PipelineHealthOptions {\n map: CaoguoMap;\n dataset: PipelineTopologyDataset;\n cellSize?: number;\n layerPrefix?: string;\n}\n\nexport interface HealthResult {\n /** 全部管段评分 */\n scores: Array<{ pipeId: string; score: PipeHealthScore }>;\n /** 热力图聚合格 */\n heatmap: HeatmapCell[];\n /** 优先维护建议 */\n maintenance: Array<{ id: string; healthScore: number; lng: number; lat: number; label?: string }>;\n /** 计算耗时 */\n durationMs: number;\n}\n\ntype Listener = (r: HealthResult) => void;\n\n/**\n * 管线健康评估组件\n */\nexport class PipelineHealth {\n private map: CaoguoMap;\n private dataset: PipelineTopologyDataset;\n private cellSize: number;\n private layerPrefix: string;\n private listeners = new Set<Listener>();\n private lastResult: HealthResult | null = null;\n private layerIds: string[] = [];\n\n constructor(options: PipelineHealthOptions) {\n this.map = options.map;\n this.dataset = options.dataset;\n this.cellSize = options.cellSize ?? 500;\n this.layerPrefix = options.layerPrefix ?? 'cg-health';\n }\n\n /** 评估全网管线健康度 */\n evaluate(weights = DEFAULT_WEIGHTS): HealthResult {\n const t0 = (typeof performance !== 'undefined' ? performance.now() : Date.now());\n const nodeById = new Map(this.dataset.nodes.map((n) => [n.id, n] as const));\n\n const scores = this.dataset.pipes.map((p) => {\n const input: PipeHealthInput = {\n installDate: p.properties?.installDate,\n material: p.properties?.material,\n failureCount: undefined,\n pressure: p.properties?.pressure,\n ratedPressure: p.properties?.ratedPressure,\n hasCathodicProtection: undefined,\n status: p.properties?.status,\n };\n return { pipeId: p.id, score: scorePipeHealth(input, weights) };\n });\n\n const points = scores.flatMap((s, i) => {\n const pipe = this.dataset.pipes[i];\n const from = nodeById.get(pipe.fromNode);\n const to = nodeById.get(pipe.toNode);\n if (!from || !to) return [];\n return [\n {\n lng: (from.lng + to.lng) / 2,\n lat: (from.lat + to.lat) / 2,\n healthScore: s.score.score,\n },\n ];\n });\n\n const heatmap = aggregateHeatmap(points, { cellSize: this.cellSize });\n const maintenance = prioritizeMaintenance(\n scores.flatMap((s, i) => {\n const pipe = this.dataset.pipes[i];\n const from = nodeById.get(pipe.fromNode);\n const to = nodeById.get(pipe.toNode);\n if (!from || !to) return [];\n return [\n {\n id: pipe.id,\n healthScore: s.score.score,\n lng: (from.lng + to.lng) / 2,\n lat: (from.lat + to.lat) / 2,\n label: pipe.id,\n },\n ];\n })\n );\n\n const durationMs =\n (typeof performance !== 'undefined' ? performance.now() : Date.now()) - t0;\n\n const result: HealthResult = { scores, heatmap, maintenance, durationMs };\n this.lastResult = result;\n this.renderHeatmap(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(): HealthResult | null {\n return this.lastResult;\n }\n\n private renderHeatmap(result: HealthResult): void {\n this.clear();\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 const data = heatmapToGeoJSON(result.heatmap);\n const sourceId = `${this.layerPrefix}-heat-src`;\n const layerId = `${this.layerPrefix}-heat-point`;\n if (!mlMap.getSource(sourceId)) mlMap.addSource(sourceId, data);\n try {\n mlMap.addLayer({\n id: layerId,\n type: 'heatmap',\n source: sourceId,\n paint: {\n 'heatmap-weight': [\n 'interpolate',\n ['linear'],\n ['get', 'healthScore'],\n 0, 1,\n 50, 0.5,\n 100, 0,\n ] as unknown,\n 'heatmap-intensity': 1,\n 'heatmap-color': [\n 'interpolate',\n ['linear'],\n ['heatmap-density'],\n 0, 'rgba(34,197,94,0)',\n 0.2, 'rgba(34,197,94,0.5)',\n 0.5, 'rgba(245,158,11,0.7)',\n 0.8, 'rgba(239,68,68,0.8)',\n 1, 'rgba(127,29,29,0.9)',\n ] as unknown,\n 'heatmap-radius': 25,\n 'heatmap-opacity': 0.7,\n },\n });\n this.layerIds.push(layerId);\n } catch {\n // ignore\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/health/healthScorer.ts","../../src/health/riskHeatmap.ts","../../src/health/PipelineHealth.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * 管线健康度评分(healthScorer)\n *\n * 6 维加权评分(PRD §4.4.2):\n * health_score = age (0.25) + material (0.20) + soil (0.15) +\n * history (0.20) + pressure (0.10) + protection (0.10)\n *\n * 每维 0-100,最终加权求和。\n * 评分模型可解释:每个维度的评分依据清晰可见。\n */\n\nimport type { PipeMaterial, PipeStatus } from '../types';\n\nexport interface PipeHealthInput {\n /** 安装日期 ISO */\n installDate?: string;\n /** 材质 */\n material?: PipeMaterial;\n /** 当前故障次数 */\n failureCount?: number;\n /** 当前压力(MPa) */\n pressure?: number;\n /** 最高允许压力(MPa) */\n ratedPressure?: number;\n /** 是否阴极保护 */\n hasCathodicProtection?: boolean;\n /** 土壤腐蚀指数 0-1(无数据时 0.5) */\n soilCorrosion?: number;\n /** 状态(damaged / under_repair 直接影响评分) */\n status?: PipeStatus;\n}\n\nexport interface PipeHealthScore {\n /** 总分 0-100 */\n score: number;\n /** 等级 */\n level: 'excellent' | 'good' | 'fair' | 'poor' | 'critical';\n /** 6 维细分 */\n dimensions: {\n age: { score: number; weight: number; reason: string };\n material: { score: number; weight: number; reason: string };\n soil: { score: number; weight: number; reason: string };\n history: { score: number; weight: number; reason: string };\n pressure: { score: number; weight: number; reason: string };\n protection: { score: number; weight: number; reason: string };\n };\n}\n\n/** 默认权重 */\nexport const DEFAULT_WEIGHTS = {\n age: 0.25,\n material: 0.2,\n soil: 0.15,\n history: 0.2,\n pressure: 0.1,\n protection: 0.1,\n};\n\nconst MATERIAL_RISK: Record<PipeMaterial, number> = {\n cast_iron: 0.85, // 铸铁 = 高风险(旧管网)\n ductile_iron: 0.2, // 球墨铸铁\n steel: 0.4,\n pe: 0.1,\n pvc: 0.15,\n concrete: 0.3,\n hdpe: 0.05,\n copper: 0.1,\n unknown: 0.5,\n};\n\n/**\n * 计算单根管线的健康度\n */\nexport function scorePipeHealth(input: PipeHealthInput, weights = DEFAULT_WEIGHTS): PipeHealthScore {\n const dims = {\n age: scoreAge(input, weights.age),\n material: scoreMaterial(input, weights.material),\n soil: scoreSoil(input, weights.soil),\n history: scoreHistory(input, weights.history),\n pressure: scorePressure(input, weights.pressure),\n protection: scoreProtection(input, weights.protection),\n };\n\n const total =\n dims.age.score * dims.age.weight +\n dims.material.score * dims.material.weight +\n dims.soil.score * dims.soil.weight +\n dims.history.score * dims.history.weight +\n dims.pressure.score * dims.pressure.weight +\n dims.protection.score * dims.protection.weight;\n\n // 损坏或维修中额外惩罚\n let final = total;\n if (input.status === 'damaged') final *= 0.5;\n else if (input.status === 'under_repair') final *= 0.7;\n else if (input.status === 'abandoned') final = 0;\n\n return {\n score: Math.round(final),\n level: toLevel(final),\n dimensions: dims,\n };\n}\n\nfunction toLevel(score: number): PipeHealthScore['level'] {\n if (score >= 80) return 'excellent';\n if (score >= 60) return 'good';\n if (score >= 40) return 'fair';\n if (score >= 20) return 'poor';\n return 'critical';\n}\n\nfunction scoreAge(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['age'] {\n if (!input.installDate) {\n return { score: 50, weight, reason: '未知安装日期,按中等计' };\n }\n const ageYears = (Date.now() - new Date(input.installDate).getTime()) / (365.25 * 24 * 3600 * 1000);\n if (ageYears < 0) return { score: 100, weight, reason: '未来日期,视为优秀' };\n if (ageYears < 5) return { score: 100, weight, reason: '新建管线 (<5年)' };\n if (ageYears < 15) return { score: 85, weight, reason: '较新 (5-15年)' };\n if (ageYears < 25) return { score: 65, weight, reason: '中龄 (15-25年)' };\n if (ageYears < 40) return { score: 40, weight, reason: '老龄 (25-40年)' };\n if (ageYears < 60) return { score: 20, weight, reason: '超期 (>40年)' };\n return { score: 5, weight, reason: '超期 (>60年)' };\n}\n\nfunction scoreMaterial(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['material'] {\n if (!input.material) {\n return { score: 50, weight, reason: '未知材质,按中等计' };\n }\n const risk = MATERIAL_RISK[input.material] ?? 0.5;\n const score = Math.round((1 - risk) * 100);\n const labels: Record<string, string> = {\n cast_iron: '铸铁(高风险)',\n ductile_iron: '球墨铸铁',\n steel: '钢',\n pe: 'PE(低风险)',\n pvc: 'PVC',\n concrete: '混凝土',\n hdpe: 'HDPE(最佳)',\n copper: '铜',\n unknown: '未知',\n };\n return {\n score,\n weight,\n reason: labels[input.material] ?? input.material,\n };\n}\n\nfunction scoreSoil(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['soil'] {\n const c = input.soilCorrosion ?? 0.5;\n const score = Math.round((1 - c) * 100);\n return {\n score,\n weight,\n reason: c === 0.5 && !input.soilCorrosion ? '无土壤数据,按平均计' : `土壤腐蚀指数 ${c.toFixed(2)}`,\n };\n}\n\nfunction scoreHistory(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['history'] {\n const fail = input.failureCount ?? 0;\n if (fail === 0) return { score: 100, weight, reason: '历史无故障' };\n if (fail === 1) return { score: 75, weight, reason: '历史 1 次故障' };\n if (fail === 2) return { score: 50, weight, reason: '历史 2 次故障' };\n if (fail === 3) return { score: 25, weight, reason: '历史 3 次故障' };\n return { score: 0, weight, reason: `历史 ≥${fail} 次故障` };\n}\n\nfunction scorePressure(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['pressure'] {\n if (!input.pressure) {\n return { score: 75, weight, reason: '无压力数据,按中等偏好计' };\n }\n if (!input.ratedPressure) {\n return { score: 75, weight, reason: '仅知当前压力' };\n }\n const ratio = input.pressure / input.ratedPressure;\n if (ratio < 0.5) return { score: 60, weight, reason: '压力偏低 (使用率 <50%)' };\n if (ratio < 0.8) return { score: 90, weight, reason: '压力正常 (使用率 50-80%)' };\n if (ratio < 1.0) return { score: 75, weight, reason: '压力偏高 (使用率 80-100%)' };\n if (ratio < 1.2) return { score: 30, weight, reason: '压力超限 (100-120%)' };\n return { score: 0, weight, reason: '压力严重超限 (>120%)' };\n}\n\nfunction scoreProtection(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['protection'] {\n if (input.hasCathodicProtection === true) {\n return { score: 90, weight, reason: '有阴极保护' };\n }\n if (input.hasCathodicProtection === false) {\n return { score: 30, weight, reason: '无阴极保护' };\n }\n return { score: 50, weight, reason: '阴保状态未知' };\n}\n\n/**\n * 批量评分(按需遍历)\n */\nexport function scorePipes(inputs: PipeHealthInput[], weights = DEFAULT_WEIGHTS): PipeHealthScore[] {\n return inputs.map((i) => scorePipeHealth(i, weights));\n}\n","/**\n * 风险热力图(riskHeatmap)\n *\n * 把 scorePipeHealth 输出按地理网格聚合,输出每个网格的平均分/最高风险,\n * 用于地图热力图(heat-map layer)。\n *\n * 输入:管线数组 [{ lng, lat, healthScore }]\n * 输出:GeoJSON FeatureCollection<Point>(含 healthScore 属性)\n */\n\nexport interface HeatmapCell {\n lng: number;\n lat: number;\n healthScore: number;\n /** 网格内管段数 */\n pipeCount: number;\n}\n\nexport interface PipeHealthPoint {\n lng: number;\n lat: number;\n healthScore: number;\n}\n\nexport interface RiskHeatmapOptions {\n /** 网格尺寸(m),默认 500 */\n cellSize?: number;\n /** 聚合方式 */\n aggregation?: 'average' | 'min' | 'max';\n}\n\nexport function aggregateHeatmap(\n points: PipeHealthPoint[],\n options: RiskHeatmapOptions = {}\n): HeatmapCell[] {\n const cell = options.cellSize ?? 500;\n const agg = options.aggregation ?? 'average';\n\n // 经纬度 → 米近似(以第一个点为原点)\n if (points.length === 0) return [];\n\n const refLat = points[0].lat;\n const refLng = points[0].lng;\n const mPerDegLat = 110_540;\n const mPerDegLng = 111_320 * Math.cos((refLat * Math.PI) / 180);\n\n const grid = new Map<string, { acc: number; count: number; minS: number; maxS: number; lng: number; lat: number }>();\n for (const p of points) {\n const x = (p.lng - refLng) * mPerDegLng;\n const y = (p.lat - refLat) * mPerDegLat;\n const cx = Math.floor(x / cell);\n const cy = Math.floor(y / cell);\n const key = `${cx}:${cy}`;\n const cur = grid.get(key);\n if (!cur) {\n grid.set(key, {\n acc: p.healthScore,\n count: 1,\n minS: p.healthScore,\n maxS: p.healthScore,\n lng: p.lng,\n lat: p.lat,\n });\n } else {\n cur.acc += p.healthScore;\n cur.count += 1;\n if (p.healthScore < cur.minS) cur.minS = p.healthScore;\n if (p.healthScore > cur.maxS) cur.maxS = p.healthScore;\n cur.lng = (cur.lng * (cur.count - 1) + p.lng) / cur.count;\n cur.lat = (cur.lat * (cur.count - 1) + p.lat) / cur.count;\n }\n }\n\n const cells: HeatmapCell[] = [];\n for (const v of grid.values()) {\n let score: number;\n if (agg === 'min') score = v.minS;\n else if (agg === 'max') score = v.maxS;\n else score = v.acc / v.count;\n cells.push({\n lng: v.lng,\n lat: v.lat,\n healthScore: Math.round(score),\n pipeCount: v.count,\n });\n }\n return cells;\n}\n\nexport function heatmapToGeoJSON(cells: HeatmapCell[]): GeoJSON.FeatureCollection<GeoJSON.Point> {\n return {\n type: 'FeatureCollection',\n features: cells.map((c) => ({\n type: 'Feature',\n geometry: { type: 'Point', coordinates: [c.lng, c.lat] },\n properties: {\n healthScore: c.healthScore,\n pipeCount: c.pipeCount,\n },\n })),\n };\n}\n\n/** 优先维护建议列表(风险最高的 Top N 管线) */\nexport function prioritizeMaintenance(\n pipes: Array<{ id: string; healthScore: number; lng: number; lat: number; label?: string }>,\n topN = 10\n) {\n return [...pipes].sort((a, b) => a.healthScore - b.healthScore).slice(0, topN);\n}\n","/**\n * PipelineHealth 组件类(地图集成层)\n */\n\nimport type { Map as CaoguoMap } from '@caoguo/maplibre';\nimport { scorePipeHealth, type PipeHealthInput, type PipeHealthScore, DEFAULT_WEIGHTS } from './healthScorer';\nimport { aggregateHeatmap, heatmapToGeoJSON, type HeatmapCell, prioritizeMaintenance } from './riskHeatmap';\nimport type { PipelineTopologyDataset } from '../types';\n\nexport interface PipelineHealthOptions {\n map: CaoguoMap;\n dataset: PipelineTopologyDataset;\n cellSize?: number;\n layerPrefix?: string;\n}\n\nexport interface HealthResult {\n /** 全部管段评分 */\n scores: Array<{ pipeId: string; score: PipeHealthScore }>;\n /** 热力图聚合格 */\n heatmap: HeatmapCell[];\n /** 优先维护建议 */\n maintenance: Array<{ id: string; healthScore: number; lng: number; lat: number; label?: string }>;\n /** 计算耗时 */\n durationMs: number;\n}\n\ntype Listener = (r: HealthResult) => void;\n\n/**\n * 管线健康评估组件\n */\nexport class PipelineHealth {\n private map: CaoguoMap;\n private dataset: PipelineTopologyDataset;\n private cellSize: number;\n private layerPrefix: string;\n private listeners = new Set<Listener>();\n private lastResult: HealthResult | null = null;\n private layerIds: string[] = [];\n\n constructor(options: PipelineHealthOptions) {\n this.map = options.map;\n this.dataset = options.dataset;\n this.cellSize = options.cellSize ?? 500;\n this.layerPrefix = options.layerPrefix ?? 'cg-health';\n }\n\n /** 评估全网管线健康度 */\n evaluate(weights = DEFAULT_WEIGHTS): HealthResult {\n const t0 = (typeof performance !== 'undefined' ? performance.now() : Date.now());\n const nodeById = new Map(this.dataset.nodes.map((n) => [n.id, n] as const));\n\n const scores = this.dataset.pipes.map((p) => {\n const input: PipeHealthInput = {\n installDate: p.properties?.installDate,\n material: p.properties?.material,\n failureCount: p.properties?.failureCount ?? 0,\n pressure: p.properties?.pressure,\n ratedPressure: p.properties?.ratedPressure,\n hasCathodicProtection: p.properties?.hasCathodicProtection ?? false,\n status: p.properties?.status,\n };\n return { pipeId: p.id, score: scorePipeHealth(input, weights) };\n });\n\n const points = scores.flatMap((s, i) => {\n const pipe = this.dataset.pipes[i];\n const from = nodeById.get(pipe.fromNode);\n const to = nodeById.get(pipe.toNode);\n if (!from || !to) return [];\n return [\n {\n lng: (from.lng + to.lng) / 2,\n lat: (from.lat + to.lat) / 2,\n healthScore: s.score.score,\n },\n ];\n });\n\n const heatmap = aggregateHeatmap(points, { cellSize: this.cellSize });\n const maintenance = prioritizeMaintenance(\n scores.flatMap((s, i) => {\n const pipe = this.dataset.pipes[i];\n const from = nodeById.get(pipe.fromNode);\n const to = nodeById.get(pipe.toNode);\n if (!from || !to) return [];\n return [\n {\n id: pipe.id,\n healthScore: s.score.score,\n lng: (from.lng + to.lng) / 2,\n lat: (from.lat + to.lat) / 2,\n label: pipe.id,\n },\n ];\n })\n );\n\n const durationMs =\n (typeof performance !== 'undefined' ? performance.now() : Date.now()) - t0;\n\n const result: HealthResult = { scores, heatmap, maintenance, durationMs };\n this.lastResult = result;\n this.renderHeatmap(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(): HealthResult | null {\n return this.lastResult;\n }\n\n private renderHeatmap(result: HealthResult): void {\n this.clear();\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 const data = heatmapToGeoJSON(result.heatmap);\n const sourceId = `${this.layerPrefix}-heat-src`;\n const layerId = `${this.layerPrefix}-heat-point`;\n if (!mlMap.getSource(sourceId)) mlMap.addSource(sourceId, data);\n try {\n mlMap.addLayer({\n id: layerId,\n type: 'heatmap',\n source: sourceId,\n paint: {\n 'heatmap-weight': [\n 'interpolate',\n ['linear'],\n ['get', 'healthScore'],\n 0, 1,\n 50, 0.5,\n 100, 0,\n ] as unknown,\n 'heatmap-intensity': 1,\n 'heatmap-color': [\n 'interpolate',\n ['linear'],\n ['heatmap-density'],\n 0, 'rgba(34,197,94,0)',\n 0.2, 'rgba(34,197,94,0.5)',\n 0.5, 'rgba(245,158,11,0.7)',\n 0.8, 'rgba(239,68,68,0.8)',\n 1, 'rgba(127,29,29,0.9)',\n ] as unknown,\n 'heatmap-radius': 25,\n 'heatmap-opacity': 0.7,\n },\n });\n this.layerIds.push(layerId);\n } catch {\n // ignore\n }\n }\n}\n"]}
@@ -1,3 +1,3 @@
1
- export { DEFAULT_WEIGHTS, PipelineHealth, aggregateHeatmap, heatmapToGeoJSON, prioritizeMaintenance, scorePipeHealth, scorePipes } from '../chunk-VA2TQWL3.js';
1
+ export { DEFAULT_WEIGHTS, PipelineHealth, aggregateHeatmap, heatmapToGeoJSON, prioritizeMaintenance, scorePipeHealth, scorePipes } from '../chunk-3656CGXE.js';
2
2
  //# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
package/dist/index.cjs CHANGED
@@ -2069,10 +2069,10 @@ var PipelineHealth = class {
2069
2069
  const input = {
2070
2070
  installDate: p.properties?.installDate,
2071
2071
  material: p.properties?.material,
2072
- failureCount: void 0,
2072
+ failureCount: p.properties?.failureCount ?? 0,
2073
2073
  pressure: p.properties?.pressure,
2074
2074
  ratedPressure: p.properties?.ratedPressure,
2075
- hasCathodicProtection: void 0,
2075
+ hasCathodicProtection: p.properties?.hasCathodicProtection ?? false,
2076
2076
  status: p.properties?.status
2077
2077
  };
2078
2078
  return { pipeId: p.id, score: scorePipeHealth(input, weights) };