fredmo commited on
Commit
ea86f50
·
verified ·
1 Parent(s): 6acf70c

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +196 -164
index.html CHANGED
@@ -7,51 +7,81 @@
7
  <script src="https://cesium.com/downloads/cesiumjs/releases/1.117/Build/Cesium/Cesium.js"></script>
8
  <link href="https://cesium.com/downloads/cesiumjs/releases/1.117/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
9
  <style>
10
- html, body, #cesiumContainer {
11
  width: 100%;
12
  height: 100%;
13
  margin: 0;
14
  padding: 0;
15
- overflow: hidden;
16
  font-family: sans-serif;
17
  }
 
 
 
 
 
 
18
  #controls {
19
  position: absolute;
20
  top: 10px;
21
  left: 10px;
22
- background: rgba(40, 40, 40, 0.8);
23
- padding: 10px;
24
- border-radius: 5px;
25
  color: white;
26
- z-index: 1;
 
27
  }
28
  #controls label {
29
- margin-right: 5px;
 
 
 
 
 
 
 
 
 
30
  }
31
  #infoBox {
32
  position: absolute;
33
- bottom: 10px;
34
  left: 10px;
35
- background: rgba(40, 40, 40, 0.8);
36
- padding: 10px;
37
- border-radius: 5px;
38
  color: white;
39
- z-index: 1;
40
- max-width: 300px;
41
  display: none; /* Hidden by default */
 
42
  }
43
  #infoBox h3 {
44
  margin-top: 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  }
46
  </style>
47
  </head>
48
  <body>
49
  <div id="cesiumContainer"></div>
50
  <div id="controls">
51
- <label for="acceleratorFilter">Filter by Accelerator:</label>
52
- <select id="acceleratorFilter">
53
- <option value="all">All Accelerators</option>
54
- </select>
55
  </div>
56
  <div id="infoBox">
57
  <h3>Location Details</h3>
@@ -64,36 +94,35 @@
64
 
65
  <script>
66
  // --- Data Preparation ---
67
- // Approximate coordinates (Latitude, Longitude)
68
  const locations = {
69
- "Council Bluffs, Iowa, USA": { lat: 41.2619, lon: -95.8608, accelerators: {} },
70
- "Eemshaven, Netherlands": { lat: 53.442, lon: 6.83, accelerators: {} },
71
- "Changhua County, Taiwan": { lat: 24.0706, lon: 120.5417, accelerators: {} },
72
- "Columbus, Ohio, USA": { lat: 39.9612, lon: -82.9988, accelerators: {} },
73
- "Dallas, Texas, USA": { lat: 32.7767, lon: -96.7970, accelerators: {} },
74
- "The Dalles, Oregon, USA": { lat: 45.5946, lon: -121.1787, accelerators: {} },
75
- "Las Vegas, Nevada, USA": { lat: 36.1699, lon: -115.1398, accelerators: {} },
76
- "St. Ghislain, Belgium": { lat: 50.446, lon: 3.82, accelerators: {} },
77
- "Jurong West, Singapore": { lat: 1.3398, lon: 103.7053, accelerators: {} },
78
- "Moncks Corner, South Carolina, USA": { lat: 33.1913, lon: -80.0195, accelerators: {} },
79
- "Ashburn, Virginia, USA": { lat: 39.0438, lon: -77.4874, accelerators: {} },
80
- "Tokyo, Japan": { lat: 35.6895, lon: 139.6917, accelerators: {} },
81
- "Sydney, Australia": { lat: -33.8688, lon: 151.2093, accelerators: {} },
82
- "Toronto, Ontario, Canada": { lat: 43.6532, lon: -79.3832, accelerators: {} },
83
- "Seoul, South Korea": { lat: 37.5665, lon: 126.9780, accelerators: {} },
84
- "Mumbai, India": { lat: 19.0760, lon: 72.8777, accelerators: {} },
85
- "London, UK": { lat: 51.5074, lon: -0.1278, accelerators: {} },
86
- "Frankfurt, Germany": { lat: 50.1109, lon: 8.6821, accelerators: {} },
87
- "Salt Lake City, Utah, USA": { lat: 40.7608, lon: -111.8910, accelerators: {} },
88
- "Hong Kong": { lat: 22.3193, lon: 114.1694, accelerators: {} },
89
- "Jakarta, Indonesia": { lat: -6.2088, lon: 106.8456, accelerators: {} },
90
- "Warsaw, Poland": { lat: 52.2297, lon: 21.0122, accelerators: {} },
91
- "Tel Aviv, Israel": { lat: 32.0853, lon: 34.7818, accelerators: {} },
92
- "Osasco, São Paulo, Brazil": { lat: -23.5325, lon: -46.7917, accelerators: {} },
93
- "Montréal, Québec, Canada": { lat: 45.5017, lon: -73.5673, accelerators: {} },
94
- "Los Angeles, California, USA": { lat: 34.0522, lon: -118.2437, accelerators: {} },
95
- "Zurich, Switzerland": { lat: 47.3769, lon: 8.5417, accelerators: {} },
96
- "Dammam, Saudi Arabia": { lat: 26.4207, lon: 50.0888, accelerators: {} }
97
  };
98
 
99
  const datacenterData = [
@@ -101,11 +130,11 @@
101
  { accelerator: "TPU v2", region: "us-central1", zones: "b, c, f", location: "Council Bluffs, Iowa, USA" },
102
  { accelerator: "TPU v2", region: "europe-west4", zones: "a", location: "Eemshaven, Netherlands" },
103
  { accelerator: "TPU v2", region: "asia-east1", zones: "c", location: "Changhua County, Taiwan" },
104
- // TPU v3 (many are repeated in source, assuming unique locations for now)
105
  { accelerator: "TPU v3", region: "us-central1", zones: "a, b, f", location: "Council Bluffs, Iowa, USA" },
106
  { accelerator: "TPU v3", region: "europe-west4", zones: "a", location: "Eemshaven, Netherlands" },
107
  // TPU v4
108
- { accelerator: "TPU v4", region: "us-central2", zones: "b", location: "Council Bluffs, Iowa, USA" }, // Note: Original data has "(?)"
109
  // TPU v5e
110
  { accelerator: "TPU v5e", region: "us-central1", zones: "a", location: "Council Bluffs, Iowa, USA" },
111
  { accelerator: "TPU v5e", region: "us-east5", zones: "a, b, c", location: "Columbus, Ohio, USA" },
@@ -117,7 +146,7 @@
117
  // TPU v5p
118
  { accelerator: "TPU v5p", region: "us-east5", zones: "a", location: "Columbus, Ohio, USA" },
119
  { accelerator: "TPU v5p", region: "europe-west4", zones: "b", location: "Eemshaven, Netherlands" },
120
- // TPU v6e (Data seems to have a typo for H100 A3 Mega, correcting as TPU v6e based on position)
121
  { accelerator: "TPU v6e", region: "us-east1", zones: "d", location: "Moncks Corner, South Carolina, USA" },
122
  { accelerator: "TPU v6e", region: "us-east5", zones: "b", location: "Columbus, Ohio, USA" },
123
  { accelerator: "TPU v6e", region: "europe-west4", zones: "a", location: "Eemshaven, Netherlands" },
@@ -225,17 +254,17 @@
225
  { accelerator: "N1+P4", region: "us-central1", zones: "a, c", location: "Council Bluffs, Iowa, USA" },
226
  { accelerator: "N1+P4", region: "us-east4", zones: "a, b, c", location: "Ashburn, Virginia, USA" },
227
  { accelerator: "N1+P4", region: "northamerica-northeast1", zones: "a, b, c", location: "Montréal, Québec, Canada" },
228
- { accelerator: "N1+P4", region: "us-west2", zones: "b, c", location: "Los Angeles, California, USA" }, // Assumed LA based on region
229
  { accelerator: "N1+P4", region: "asia-southeast1", zones: "b, c", location: "Jurong West, Singapore" },
230
  { accelerator: "N1+P4", region: "australia-southeast1", zones: "a, b", location: "Sydney, Australia" },
231
  { accelerator: "N1+P4", region: "europe-west4", zones: "b, c", location: "Eemshaven, Netherlands" },
232
  ];
233
 
234
- // Group accelerators by physical location for easier display and entity creation
235
  const groupedLocations = {};
236
  datacenterData.forEach(item => {
237
  if (!locations[item.location]) {
238
- console.warn(`Location data for "${item.location}" not found. Skipping.`);
239
  return;
240
  }
241
  if (!groupedLocations[item.location]) {
@@ -243,146 +272,149 @@
243
  lat: locations[item.location].lat,
244
  lon: locations[item.location].lon,
245
  name: item.location,
246
- accelerators: [],
247
- regions: new Set(), // To store unique region IDs for this location
248
- zones: new Set() // To store unique zones for this location
249
  };
250
  }
251
- // Add accelerator if not already listed for this location
252
- if (!groupedLocations[item.location].accelerators.some(acc => acc.type === item.accelerator)) {
253
- groupedLocations[item.location].accelerators.push({
254
- type: item.accelerator,
255
- region: item.region,
256
- zones: item.zones
257
- });
258
- }
259
- // Consolidate region and zone info at the location level
260
- // This part is tricky because region/zones can be specific to an accelerator
261
- // For simplicity, we'll list all associated, but for precise info, click is needed
262
  groupedLocations[item.location].regions.add(item.region);
263
  item.zones.split(',').map(z => z.trim()).forEach(z => groupedLocations[item.location].zones.add(z));
264
  });
265
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
266
 
267
- // Cesium.Ion.defaultAccessToken = 'YOUR_CESIUM_ION_ACCESS_TOKEN'; // Only if using Cesium Ion assets
 
 
 
268
 
269
- const viewer = new Cesium.Viewer('cesiumContainer', {
270
- terrainProvider: Cesium.createWorldTerrain(), // Optional: adds terrain
271
- // imageryProvider: new Cesium.OpenStreetMapImageryProvider({ // Optional: different base map
272
- // url : 'https://a.tile.openstreetmap.org/'
273
- // }),
274
- animation: false,
275
- timeline: false,
276
- geocoder: false,
277
- homeButton: false,
278
- sceneModePicker: false,
279
- baseLayerPicker: false,
280
- navigationHelpButton: false,
281
- fullscreenButton: false,
282
- });
283
 
284
- viewer.camera.flyTo({
285
- destination: Cesium.Cartesian3.fromDegrees(-95, 38, 15000000), // Fly to a general view of the US
286
- duration: 3
287
- });
288
 
289
- const acceleratorFilter = document.getElementById('acceleratorFilter');
290
- const infoBox = document.getElementById('infoBox');
291
  const locationNameEl = document.getElementById('locationName');
292
  const regionIdEl = document.getElementById('regionId');
293
  const zoneIdEl = document.getElementById('zoneId');
294
  const acceleratorListEl = document.getElementById('acceleratorList');
295
 
296
- const uniqueAccelerators = new Set();
297
- datacenterData.forEach(dc => uniqueAccelerators.add(dc.accelerator));
298
- uniqueAccelerators.forEach(acc => {
299
- const option = document.createElement('option');
300
- option.value = acc;
301
- option.textContent = acc;
302
- acceleratorFilter.appendChild(option);
303
- });
304
-
305
  const locationEntities = [];
306
 
307
- Object.values(groupedLocations).forEach(locData => {
308
- if (locData.lat === undefined || locData.lon === undefined) {
309
- console.warn(`Missing coordinates for ${locData.name}`);
310
- return;
311
- }
312
- const entity = viewer.entities.add({
313
- position: Cesium.Cartesian3.fromDegrees(locData.lon, locData.lat),
314
- point: {
315
- pixelSize: 10,
316
- color: Cesium.Color.DODGERBLUE,
317
- outlineColor: Cesium.Color.WHITE,
318
- outlineWidth: 2
319
- },
320
- label: {
321
- text: locData.name,
322
- font: '12pt monospace',
323
- style: Cesium.LabelStyle.FILL_AND_OUTLINE,
324
- outlineWidth: 2,
325
- verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
326
- pixelOffset: new Cesium.Cartesian2(0, -12)
327
- },
328
- properties: { // Custom properties
329
- name: locData.name,
330
- accelerators: locData.accelerators, // Array of {type, region, zones}
331
- all_regions_at_location: Array.from(locData.regions).join(', '),
332
- all_zones_at_location: Array.from(locData.zones).join(', ')
333
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
334
  });
335
- locationEntities.push(entity);
336
- });
337
 
 
 
 
338
 
339
- acceleratorFilter.addEventListener('change', (event) => {
340
- const selectedAccelerator = event.target.value;
341
- infoBox.style.display = 'none'; // Hide info box on filter change
342
-
343
- locationEntities.forEach(entity => {
344
- if (selectedAccelerator === 'all') {
345
- entity.show = true;
346
- } else {
347
- // Check if any of the accelerators at this location match the filter
348
- const hasAccelerator = entity.properties.accelerators.getValue().some(acc => acc.type === selectedAccelerator);
349
- entity.show = hasAccelerator;
350
- }
351
  });
352
- });
353
 
354
- // Handle clicks on entities
355
- viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
356
- const pickedObject = viewer.scene.pick(movement.position);
357
- infoBox.style.display = 'none'; // Hide by default
358
 
359
- if (Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id) && Cesium.defined(pickedObject.id.properties)) {
360
- const properties = pickedObject.id.properties;
361
- const locationName = properties.name.getValue();
362
- const acceleratorsAtLocation = properties.accelerators.getValue(); // This is an array of {type, region, zones}
363
-
364
- locationNameEl.textContent = locationName;
 
365
 
366
- // Collect all regions and zones for *this specific picked location*
367
- const regionsForDisplay = new Set();
368
- const zonesForDisplay = new Set();
369
- acceleratorListEl.innerHTML = ''; // Clear previous list
370
 
371
- acceleratorsAtLocation.forEach(acc => {
372
- regionsForDisplay.add(acc.region);
373
- acc.zones.split(',').map(z => z.trim()).forEach(zone => zonesForDisplay.add(zone));
 
 
 
 
 
 
 
 
374
 
375
- const listItem = document.createElement('li');
376
- listItem.textContent = `${acc.type} (Region: ${acc.region}, Zones: ${acc.zones})`;
377
- acceleratorListEl.appendChild(listItem);
378
- });
379
 
380
- regionIdEl.textContent = Array.from(regionsForDisplay).join(', ') || 'N/A';
381
- zoneIdEl.textContent = Array.from(zonesForDisplay).sort().join(', ') || 'N/A';
382
-
383
- infoBox.style.display = 'block';
384
- }
385
- }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
386
 
387
  </script>
388
  </body>
 
7
  <script src="https://cesium.com/downloads/cesiumjs/releases/1.117/Build/Cesium/Cesium.js"></script>
8
  <link href="https://cesium.com/downloads/cesiumjs/releases/1.117/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
9
  <style>
10
+ html, body {
11
  width: 100%;
12
  height: 100%;
13
  margin: 0;
14
  padding: 0;
15
+ overflow: hidden; /* Important to prevent scrollbars from interfering */
16
  font-family: sans-serif;
17
  }
18
+ #cesiumContainer {
19
+ width: 100%;
20
+ height: 100%;
21
+ /* visibility: visible !important; Ensure it's not hidden by other styles */
22
+ /* background-color: lightblue; Add a temporary background to see if the div itself is rendered */
23
+ }
24
  #controls {
25
  position: absolute;
26
  top: 10px;
27
  left: 10px;
28
+ background: rgba(40, 40, 40, 0.85);
29
+ padding: 12px;
30
+ border-radius: 8px;
31
  color: white;
32
+ z-index: 10; /* Ensure it's above the map */
33
+ box-shadow: 0 2px 5px rgba(0,0,0,0.2);
34
  }
35
  #controls label {
36
+ margin-right: 8px;
37
+ font-weight: bold;
38
+ }
39
+ #acceleratorSearch {
40
+ padding: 8px;
41
+ border-radius: 4px;
42
+ border: 1px solid #555;
43
+ background-color: #333;
44
+ color: white;
45
+ width: 250px; /* Adjust as needed */
46
  }
47
  #infoBox {
48
  position: absolute;
49
+ bottom: 20px; /* Increased spacing */
50
  left: 10px;
51
+ background: rgba(40, 40, 40, 0.85);
52
+ padding: 15px;
53
+ border-radius: 8px;
54
  color: white;
55
+ z-index: 10;
56
+ max-width: 350px; /* Slightly wider */
57
  display: none; /* Hidden by default */
58
+ box-shadow: 0 2px 5px rgba(0,0,0,0.2);
59
  }
60
  #infoBox h3 {
61
  margin-top: 0;
62
+ margin-bottom: 10px;
63
+ border-bottom: 1px solid #555;
64
+ padding-bottom: 5px;
65
+ }
66
+ #infoBox p {
67
+ margin: 5px 0;
68
+ }
69
+ #acceleratorList {
70
+ list-style-type: none;
71
+ padding-left: 0;
72
+ max-height: 150px; /* Prevent very long lists */
73
+ overflow-y: auto; /* Add scroll for long lists */
74
+ }
75
+ #acceleratorList li {
76
+ padding: 3px 0;
77
  }
78
  </style>
79
  </head>
80
  <body>
81
  <div id="cesiumContainer"></div>
82
  <div id="controls">
83
+ <label for="acceleratorSearch">Search Accelerators:</label>
84
+ <input type="text" id="acceleratorSearch" placeholder="E.g., TPU v5e, H100, A100...">
 
 
85
  </div>
86
  <div id="infoBox">
87
  <h3>Location Details</h3>
 
94
 
95
  <script>
96
  // --- Data Preparation ---
 
97
  const locations = {
98
+ "Council Bluffs, Iowa, USA": { lat: 41.2619, lon: -95.8608 },
99
+ "Eemshaven, Netherlands": { lat: 53.442, lon: 6.83 },
100
+ "Changhua County, Taiwan": { lat: 24.0706, lon: 120.5417 },
101
+ "Columbus, Ohio, USA": { lat: 39.9612, lon: -82.9988 },
102
+ "Dallas, Texas, USA": { lat: 32.7767, lon: -96.7970 },
103
+ "The Dalles, Oregon, USA": { lat: 45.5946, lon: -121.1787 },
104
+ "Las Vegas, Nevada, USA": { lat: 36.1699, lon: -115.1398 },
105
+ "St. Ghislain, Belgium": { lat: 50.446, lon: 3.82 },
106
+ "Jurong West, Singapore": { lat: 1.3398, lon: 103.7053 },
107
+ "Moncks Corner, South Carolina, USA": { lat: 33.1913, lon: -80.0195 },
108
+ "Ashburn, Virginia, USA": { lat: 39.0438, lon: -77.4874 },
109
+ "Tokyo, Japan": { lat: 35.6895, lon: 139.6917 },
110
+ "Sydney, Australia": { lat: -33.8688, lon: 151.2093 },
111
+ "Toronto, Ontario, Canada": { lat: 43.6532, lon: -79.3832 },
112
+ "Seoul, South Korea": { lat: 37.5665, lon: 126.9780 },
113
+ "Mumbai, India": { lat: 19.0760, lon: 72.8777 },
114
+ "London, UK": { lat: 51.5074, lon: -0.1278 },
115
+ "Frankfurt, Germany": { lat: 50.1109, lon: 8.6821 },
116
+ "Salt Lake City, Utah, USA": { lat: 40.7608, lon: -111.8910 },
117
+ "Hong Kong": { lat: 22.3193, lon: 114.1694 },
118
+ "Jakarta, Indonesia": { lat: -6.2088, lon: 106.8456 },
119
+ "Warsaw, Poland": { lat: 52.2297, lon: 21.0122 },
120
+ "Tel Aviv, Israel": { lat: 32.0853, lon: 34.7818 },
121
+ "Osasco, São Paulo, Brazil": { lat: -23.5325, lon: -46.7917 },
122
+ "Montréal, Québec, Canada": { lat: 45.5017, lon: -73.5673 },
123
+ "Los Angeles, California, USA": { lat: 34.0522, lon: -118.2437 },
124
+ "Zurich, Switzerland": { lat: 47.3769, lon: 8.5417 },
125
+ "Dammam, Saudi Arabia": { lat: 26.4207, lon: 50.0888 }
126
  };
127
 
128
  const datacenterData = [
 
130
  { accelerator: "TPU v2", region: "us-central1", zones: "b, c, f", location: "Council Bluffs, Iowa, USA" },
131
  { accelerator: "TPU v2", region: "europe-west4", zones: "a", location: "Eemshaven, Netherlands" },
132
  { accelerator: "TPU v2", region: "asia-east1", zones: "c", location: "Changhua County, Taiwan" },
133
+ // TPU v3
134
  { accelerator: "TPU v3", region: "us-central1", zones: "a, b, f", location: "Council Bluffs, Iowa, USA" },
135
  { accelerator: "TPU v3", region: "europe-west4", zones: "a", location: "Eemshaven, Netherlands" },
136
  // TPU v4
137
+ { accelerator: "TPU v4", region: "us-central2", zones: "b", location: "Council Bluffs, Iowa, USA" },
138
  // TPU v5e
139
  { accelerator: "TPU v5e", region: "us-central1", zones: "a", location: "Council Bluffs, Iowa, USA" },
140
  { accelerator: "TPU v5e", region: "us-east5", zones: "a, b, c", location: "Columbus, Ohio, USA" },
 
146
  // TPU v5p
147
  { accelerator: "TPU v5p", region: "us-east5", zones: "a", location: "Columbus, Ohio, USA" },
148
  { accelerator: "TPU v5p", region: "europe-west4", zones: "b", location: "Eemshaven, Netherlands" },
149
+ // TPU v6e
150
  { accelerator: "TPU v6e", region: "us-east1", zones: "d", location: "Moncks Corner, South Carolina, USA" },
151
  { accelerator: "TPU v6e", region: "us-east5", zones: "b", location: "Columbus, Ohio, USA" },
152
  { accelerator: "TPU v6e", region: "europe-west4", zones: "a", location: "Eemshaven, Netherlands" },
 
254
  { accelerator: "N1+P4", region: "us-central1", zones: "a, c", location: "Council Bluffs, Iowa, USA" },
255
  { accelerator: "N1+P4", region: "us-east4", zones: "a, b, c", location: "Ashburn, Virginia, USA" },
256
  { accelerator: "N1+P4", region: "northamerica-northeast1", zones: "a, b, c", location: "Montréal, Québec, Canada" },
257
+ { accelerator: "N1+P4", region: "us-west2", zones: "b, c", location: "Los Angeles, California, USA" },
258
  { accelerator: "N1+P4", region: "asia-southeast1", zones: "b, c", location: "Jurong West, Singapore" },
259
  { accelerator: "N1+P4", region: "australia-southeast1", zones: "a, b", location: "Sydney, Australia" },
260
  { accelerator: "N1+P4", region: "europe-west4", zones: "b, c", location: "Eemshaven, Netherlands" },
261
  ];
262
 
263
+ // Group accelerators by physical location
264
  const groupedLocations = {};
265
  datacenterData.forEach(item => {
266
  if (!locations[item.location]) {
267
+ console.warn(`Location data for "${item.location}" not found. Skipping item:`, item);
268
  return;
269
  }
270
  if (!groupedLocations[item.location]) {
 
272
  lat: locations[item.location].lat,
273
  lon: locations[item.location].lon,
274
  name: item.location,
275
+ accelerators: [], // Will store {type, region, zones}
276
+ regions: new Set(),
277
+ zones: new Set()
278
  };
279
  }
280
+ groupedLocations[item.location].accelerators.push({
281
+ type: item.accelerator,
282
+ region: item.region,
283
+ zones: item.zones
284
+ });
 
 
 
 
 
 
285
  groupedLocations[item.location].regions.add(item.region);
286
  item.zones.split(',').map(z => z.trim()).forEach(z => groupedLocations[item.location].zones.add(z));
287
  });
288
 
289
+ let viewer;
290
+ try {
291
+ viewer = new Cesium.Viewer('cesiumContainer', {
292
+ // Simplified for basic rendering. Add back features like terrainProvider later.
293
+ animation: false,
294
+ timeline: false,
295
+ geocoder: false,
296
+ homeButton: true, // Keep home button for now
297
+ sceneModePicker: true, // Useful for switching between 3D, 2.5D, 2D
298
+ baseLayerPicker: true, // Allows changing base map
299
+ navigationHelpButton: false,
300
+ fullscreenButton: true,
301
+ infoBox: false // We are using a custom info box
302
+ });
303
+ console.log("Cesium Viewer initialized successfully.");
304
 
305
+ viewer.camera.flyTo({
306
+ destination: Cesium.Cartesian3.fromDegrees(-95, 38, 15000000),
307
+ duration: 0 // Fly immediately
308
+ });
309
 
310
+ } catch (error) {
311
+ console.error("Error initializing Cesium Viewer:", error);
312
+ alert("Could not initialize the 3D map. Please check the console for errors (F12). It might be a WebGL issue or a problem loading CesiumJS.");
313
+ // Hide controls if map fails to load
314
+ document.getElementById('controls').style.display = 'none';
315
+ document.getElementById('infoBox').style.display = 'none';
316
+ }
 
 
 
 
 
 
 
317
 
 
 
 
 
318
 
319
+ const acceleratorSearchInput = document.getElementById('acceleratorSearch');
320
+ const infoBoxEl = document.getElementById('infoBox');
321
  const locationNameEl = document.getElementById('locationName');
322
  const regionIdEl = document.getElementById('regionId');
323
  const zoneIdEl = document.getElementById('zoneId');
324
  const acceleratorListEl = document.getElementById('acceleratorList');
325
 
 
 
 
 
 
 
 
 
 
326
  const locationEntities = [];
327
 
328
+ if (viewer) { // Only proceed if viewer was initialized
329
+ Object.values(groupedLocations).forEach(locData => {
330
+ if (locData.lat === undefined || locData.lon === undefined) {
331
+ console.warn(`Missing coordinates for ${locData.name}, cannot plot.`);
332
+ return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
333
  }
334
+ const entity = viewer.entities.add({
335
+ position: Cesium.Cartesian3.fromDegrees(locData.lon, locData.lat),
336
+ point: {
337
+ pixelSize: 10,
338
+ color: Cesium.Color.ORANGERED, // Changed color for better visibility
339
+ outlineColor: Cesium.Color.WHITE,
340
+ outlineWidth: 2,
341
+ disableDepthTestDistance: Number.POSITIVE_INFINITY // Ensures point is visible even if behind terrain
342
+ },
343
+ label: {
344
+ text: locData.name,
345
+ font: '12pt Segoe UI, sans-serif', // More readable font
346
+ style: Cesium.LabelStyle.FILL_AND_OUTLINE,
347
+ outlineWidth: 3,
348
+ outlineColor: Cesium.Color.BLACK,
349
+ verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
350
+ pixelOffset: new Cesium.Cartesian2(0, -15), // Adjusted offset
351
+ distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0.0, 10000000.0) // Hide label when far away
352
+ },
353
+ properties: {
354
+ name: locData.name,
355
+ accelerators: locData.accelerators, // Array of {type, region, zones}
356
+ // The following are consolidated for the location, specific assignments are in accelerators array
357
+ all_regions_at_location: Array.from(locData.regions).join(', '),
358
+ all_zones_at_location: Array.from(locData.zones).sort().join(', ')
359
+ }
360
+ });
361
+ locationEntities.push(entity);
362
  });
 
 
363
 
364
+ acceleratorSearchInput.addEventListener('input', (event) => {
365
+ const searchTerm = event.target.value.toLowerCase().trim();
366
+ infoBoxEl.style.display = 'none';
367
 
368
+ locationEntities.forEach(entity => {
369
+ if (!searchTerm) { // If search bar is empty, show all
370
+ entity.show = true;
371
+ } else {
372
+ const hasAccelerator = entity.properties.accelerators.getValue().some(acc =>
373
+ acc.type.toLowerCase().includes(searchTerm)
374
+ );
375
+ entity.show = hasAccelerator;
376
+ }
377
+ });
 
 
378
  });
 
379
 
380
+ viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
381
+ const pickedObject = viewer.scene.pick(movement.position);
382
+ infoBoxEl.style.display = 'none';
 
383
 
384
+ if (Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id) && Cesium.defined(pickedObject.id.properties)) {
385
+ const properties = pickedObject.id.properties;
386
+ const locationName = properties.name.getValue();
387
+ const acceleratorsAtLocation = properties.accelerators.getValue(); // Array of {type, region, zones}
388
+
389
+ locationNameEl.textContent = locationName;
390
+ acceleratorListEl.innerHTML = ''; // Clear previous list
391
 
392
+ const uniqueRegionsForDisplay = new Set();
393
+ const uniqueZonesForDisplay = new Set();
 
 
394
 
395
+ if (acceleratorsAtLocation && acceleratorsAtLocation.length > 0) {
396
+ acceleratorsAtLocation.forEach(acc => {
397
+ const listItem = document.createElement('li');
398
+ listItem.textContent = `${acc.type} (Region: ${acc.region}, Zones: ${acc.zones})`;
399
+ acceleratorListEl.appendChild(listItem);
400
+ uniqueRegionsForDisplay.add(acc.region);
401
+ acc.zones.split(',').map(z => z.trim()).forEach(zone => uniqueZonesForDisplay.add(zone));
402
+ });
403
+ } else {
404
+ acceleratorListEl.innerHTML = '<li>No specific accelerator data.</li>';
405
+ }
406
 
407
+ regionIdEl.textContent = Array.from(uniqueRegionsForDisplay).join(', ') || 'N/A';
408
+ zoneIdEl.textContent = Array.from(uniqueZonesForDisplay).sort().join(', ') || 'N/A';
409
+
410
+ infoBoxEl.style.display = 'block';
411
 
412
+ // Optionally fly to the picked entity
413
+ viewer.flyTo(pickedObject.id, {duration: 0.5});
414
+
415
+ }
416
+ }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
417
+ } // end if(viewer)
418
 
419
  </script>
420
  </body>