PageSourceSearch

https://wikiglo.be/js/layers/power-plants.js

js wikiglo.be collected 2026-09-28 07:09:37 UTC 2,714 bytes, 87 lines download raw bytes

1// Power plants layer: reads committed JSON from the data pipeline
2// (scripts/data/update-power-plants.mjs → data/power-plants.latest.json).
3// Points colored by fuel type, sized by capacity (capped).
4
5const DATA_URL = "data/power-plants.latest.json";
6
7const FUEL_COLORS = {
8  Solar:       [251, 191, 36],
9  Hydro:       [59, 130, 246],
10  Wind:        [45, 212, 191],
11  Gas:         [251, 146, 60],
12  Coal:        [120, 113, 108],
13  Oil:         [168, 85, 247],
14  Biomass:     [63, 217, 143],
15  Waste:       [148, 163, 184],
16  Nuclear:     [236, 72, 153],
17  Geothermal:  [239, 68, 68],
18  Storage:     [99, 102, 241],
19  Other:       [161, 161, 170],
20  Cogeneration:[217, 119, 6],
21  Petcoke:     [87, 83, 78],
22  "Wave and Tidal": [34, 197, 94],
23};
24
25export class PowerPlantsLayer {
26  constructor(viewer) {
27    this.viewer = viewer;
28    this.points = viewer.scene.primitives.add(new Cesium.PointPrimitiveCollection());
29    this.plants = [];
30    this.source = "loading";
31    this.visible = false;
32    this.loaded = false;
33    this.fuels = [];
34  }
35
36  async init() {
37    this.points.show = false;
38    try {
39      const resp = await fetch(DATA_URL);
40      if (!resp.ok) throw new Error(`${DATA_URL} HTTP ${resp.status}`);
41      const data = await resp.json();
42      this._build(data);
43      this.source = "data";
44      this.loaded = true;
45    } catch (e) {
46      console.warn("[power-plants] data load failed:", e.message);
47      this.source = "idle";
48    }
49  }
50
51  _build(data) {
52    this.fuels = data.meta?.fuels ?? [];
53    const plants = data.plants ?? [];
54    for (const [lon, lat, fuelIdx, mw, name, country] of plants) {
55      const fuelName = this.fuels[fuelIdx] ?? "Other";
56      const color = FUEL_COLORS[fuelName] ?? FUEL_COLORS.Other;
57      // Size: 4 + sqrt(mw)/4, capped at 14
58      const size = Math.max(3, Math.min(14, 4 + Math.sqrt(mw) / 4));
59      const point = this.points.add({
60        position: Cesium.Cartesian3.fromDegrees(lon, lat),
61        pixelSize: size,
62        color: Cesium.Color.fromBytes(color[0], color[1], color[2], 200),
63        outlineColor: Cesium.Color.fromBytes(color[0], color[1], color[2], 80),
64        outlineWidth: 1,
65        scaleByDistance: new Cesium.NearFarScalar(2.0e5, 1.4, 5.0e7, 0.4),
66        id: { kind: "plant", plant: null },
67        show: this.visible,
68      });
69      const p = { lon, lat, fuel: fuelName, mw, name, country, point };
70      point.id = { kind: "plant", plant: p };
71      this.plants.push(p);
72    }
73  }
74
75  setVisible(v) {
76    this.visible = v;
77    this.points.show = v;
78  }
79
80  counts() {
81    return {
82      count: this.visible ? this.plants.length : 0,
83      source: this.source,
84      detail: `${this.plants.length} plants · WRI GPPD`,
85    };
86  }
87}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.