@a2f0/skyline 0.2.29 → 0.2.30

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.
@@ -478,7 +478,8 @@ Intermediate parts have less certainty than the overall height:
478
478
  drawn tower there stands about 140 layer units higher, so the drawing's group keeps its
479
479
  label; see the [Three Illinois Center reference audit](three-illinois-center-reference.md).
480
480
  - Swissôtel Chicago stands behind Three Illinois Center and The Buckingham. Its triangular
481
- glass tower takes the published 139.3 m over OpenStreetMap's 45 levels, a panel to each,
481
+ glass tower retains the published 139.3 m over 45 facade modules, each divided
482
+ into an opaque floor band and a vision panel using 2012 photographic ratios,
482
483
  and its west corner closes the seam where those two models' corners leave sky; see the
483
484
  [Swissôtel reference audit](swissotel-reference.md).
484
485
 
@@ -263,7 +263,7 @@ export const colourMaterials = {
263
263
  // Reflective blue-green glass in its frame.
264
264
  "building-swissotel": {
265
265
  shell: ["neutral"],
266
- "curtain wall": ["blue-green glass", windows(0x878787, 0x515151)],
266
+ "curtain wall": ["blue-green glass", { ...windows(0x878787, 0x515151), 0x414141: "aluminium", 0x909090: "opaque spandrel" }],
267
267
  },
268
268
  };
269
269
  // A batch's materials from its mesh's name, if the trial knows the building and the batch.
@@ -204,6 +204,9 @@ export const measuredColours = {
204
204
  // docs/swissotel-reference.md, 2026-10-10 — Daytime colours from Chicago.jpg.
205
205
  "building-swissotel": {
206
206
  ...glass(0x475056, "blue-green glass"),
207
+ // FID-SWI-002: mixed panorama sample does not resolve these separately.
208
+ "opaque spandrel": null,
209
+ aluminium: null,
207
210
  neutral: null,
208
211
  },
209
212
  // docs/north-michigan-180-reference.md, 2026-10-10 — Daytime colours from Chicago.jpg. Only the
@@ -46,7 +46,7 @@ export const geographicBuildings = [
46
46
  { "id": "building-hyatt-regency-west-tower", "name": "Hyatt Regency Chicago West Tower", "shortName": "Hyatt West Tower", "height": 111.3, "tipHeight": 111.3, "heightSource": "https://www.skyscrapercenter.com/building/hyatt-regency-chicago-west-tower/13132", "note": "Detailed Hyatt Regency Chicago West Tower: its mapped part of the hotel's outline; a brick slab of 33 storeys, narrow window slots continuous from the lobby to the top two floors on a 3.5 m module between solid corners, and a plain band over them to a flat roof at the Skyscraper Center's 111.3 m. From the photograph's camera it stands between Aon Center and the Blue Cross and Blue Shield Tower, where the drawing's Blue Cross group paints a dark brown sliver.", "footprint": { "way": 235920252, "version": 4, "coordinates": [[-87.6227574, 41.887587], [-87.6228537, 41.887584], [-87.6228521, 41.8874603], [-87.6228518, 41.8874165], [-87.6225427, 41.8874231], [-87.6225408, 41.8875106], [-87.6225253, 41.8875109], [-87.6225266, 41.8875277], [-87.6225277, 41.8875513], [-87.622528, 41.8875746], [-87.6225382, 41.8878947], [-87.62255, 41.8878954], [-87.6225496, 41.8879846], [-87.6228658, 41.8879789], [-87.6228643, 41.8879388], [-87.6228611, 41.8878099], [-87.6227664, 41.8878103]] }, "parts": [{ "way": 235920252, "version": 4, "coordinates": [[-87.6227574, 41.887587], [-87.6228537, 41.887584], [-87.6228521, 41.8874603], [-87.6228518, 41.8874165], [-87.6225427, 41.8874231], [-87.6225408, 41.8875106], [-87.6225253, 41.8875109], [-87.6225266, 41.8875277], [-87.6225277, 41.8875513], [-87.622528, 41.8875746], [-87.6225382, 41.8878947], [-87.62255, 41.8878954], [-87.6225496, 41.8879846], [-87.6228658, 41.8879789], [-87.6228643, 41.8879388], [-87.6228611, 41.8878099], [-87.6227664, 41.8878103]], "bottom": 0, "top": 111.3 }] },
47
47
  { "id": "building-buckingham-east", "name": "Sheraton Grand Chicago Riverwalk", "shortName": "Sheraton Grand", "height": 112.3, "tipHeight": 112.3, "heightSource": "https://www.skyscrapercenter.com/building/sheraton-chicago-hotel-towers/10020", "note": "Detailed Sheraton Grand Chicago Riverwalk: the mapped tower and its corner part; a cream precast tower on an L of punched windows at Emporis's 2.67 m floor-to-floor, its arms to 94.76 m, the corner's round tower two floors higher to 100.1 m, and pale stepped frames under dark louvered screens on all four round ends, with the smaller bases approximated from the principal frame. The main crown reaches the Skyscraper Center's 112.3 m. Heights stand on the Skyscraper Center's datum: its top floor at 97 m, a floor-to-roof of 3.1 m and a 12.2 m main crown from Emporis; photographic ratios estimate about 7.2 m crowns on the arms and 6 m on the east wing; the published height nearest the drawing's reading, over Emporis's 330.56 ft. The Skyscraper Center's 112.8 m tip, 50 cm over the drum, is not modelled. The drawing's buckingham-east group is its corner's lit drum over its tower. The mapped east wing and its round end continue the hotel to the east, with estimated roofs at 84.08 m and 86.75 m on the same height datum and a fourth crown. Photographs from before 2013 establish the wing; exact roof and crown dimensions remain inferred.", "footprint": { "way": 592122464, "version": 5, "coordinates": [[-87.6199499, 41.8891119], [-87.6199176, 41.8893381], [-87.6199306, 41.8893589], [-87.6199502, 41.8893716], [-87.6199845, 41.8893878], [-87.6200276, 41.8893957], [-87.6200732, 41.8893915], [-87.6201147, 41.8893744], [-87.6201372, 41.8893482], [-87.6201463, 41.8893162], [-87.6201584, 41.8892447], [-87.6201841, 41.889063], [-87.6201875, 41.8890302], [-87.6201812, 41.8889946], [-87.6201588, 41.8889641], [-87.620121, 41.8889384], [-87.6200743, 41.8889276], [-87.6196505, 41.8888958], [-87.6196025, 41.8889162], [-87.6195726, 41.8889427], [-87.6195591, 41.8889735], [-87.6195627, 41.8890068], [-87.6195846, 41.8890373], [-87.6196228, 41.8890638], [-87.6198263, 41.8890777], [-87.6198225, 41.889104]] }, "parts": [{ "way": 592122464, "version": 5, "coordinates": [[-87.6199499, 41.8891119], [-87.6199176, 41.8893381], [-87.6199306, 41.8893589], [-87.6199502, 41.8893716], [-87.6199845, 41.8893878], [-87.6200276, 41.8893957], [-87.6200732, 41.8893915], [-87.6201147, 41.8893744], [-87.6201372, 41.8893482], [-87.6201463, 41.8893162], [-87.6201584, 41.8892447], [-87.6201841, 41.889063], [-87.6201875, 41.8890302], [-87.6201812, 41.8889946], [-87.6201588, 41.8889641], [-87.620121, 41.8889384], [-87.6200743, 41.8889276], [-87.6196505, 41.8888958], [-87.6196025, 41.8889162], [-87.6195726, 41.8889427], [-87.6195591, 41.8889735], [-87.6195627, 41.8890068], [-87.6195846, 41.8890373], [-87.6196228, 41.8890638], [-87.6198263, 41.8890777], [-87.6198225, 41.889104]], "bottom": 0, "top": 94.76 }, { "way": 1269924307, "version": 1, "coordinates": [[-87.6199691, 41.8890378], [-87.6199677, 41.889013], [-87.6199719, 41.8889952], [-87.6199903, 41.8889744], [-87.6200135, 41.88896], [-87.6200416, 41.8889517], [-87.6200717, 41.8889503], [-87.6201037, 41.8889568], [-87.6201308, 41.8889711], [-87.6201498, 41.8889914], [-87.6201583, 41.8890152], [-87.6201555, 41.8890398], [-87.6201415, 41.8890622], [-87.6201241, 41.8890776], [-87.6200882, 41.8890904], [-87.6200552, 41.8890928], [-87.6200258, 41.8890875], [-87.6200001, 41.8890757], [-87.6199805, 41.8890586]], "bottom": 94.76, "top": 100.1 }, { "way": 1269924305, "version": 1, "coordinates": [[-87.6191033, 41.8890226], [-87.6190622, 41.8889954], [-87.6190428, 41.8889627], [-87.6190431, 41.8889236], [-87.6190607, 41.8888928], [-87.619091, 41.8888724], [-87.6191278, 41.8888566], [-87.6193634, 41.8888743], [-87.6196505, 41.8888958], [-87.6196025, 41.8889162], [-87.6195726, 41.8889427], [-87.6195591, 41.8889735], [-87.6195627, 41.8890068], [-87.6195846, 41.8890373], [-87.6196228, 41.8890638]], "bottom": 0, "top": 84.08, "estimatedHeight": true }, { "way": 1269924304, "version": 1, "coordinates": [[-87.619112, 41.8888866], [-87.61909, 41.8888996], [-87.6190746, 41.888917], [-87.6190672, 41.8889372], [-87.6190685, 41.8889581], [-87.6190786, 41.8889777], [-87.6190963, 41.8889939], [-87.6191199, 41.8890052], [-87.6191471, 41.8890105], [-87.6191778, 41.8890088], [-87.6192059, 41.8889994], [-87.619228, 41.8889835], [-87.6192416, 41.8889629], [-87.6192449, 41.8889401], [-87.6192376, 41.8889179], [-87.6192207, 41.8888988], [-87.6191959, 41.8888851], [-87.6191665, 41.8888785], [-87.6191384, 41.8888793]], "bottom": 84.08, "top": 86.75, "estimatedHeight": true }], "groundFootprintWays": [592122464, 1269924305] },
48
48
  { "id": "building-three-illinois-center", "name": "Three Illinois Center", "shortName": "Three Illinois Center", "height": 106.7, "tipHeight": 106.7, "heightSource": "https://www.skyscrapercenter.com/building/three-illinois-center/13913", "note": "Detailed Three Illinois Center: the mapped outline; a dark bronze curtain wall of 30 storeys, mullions on a 5 ft module and glass over a spandrel on each floor at the published 11.5 ft slab to slab over a 5.06 m lobby, and the top two floors' windowless mechanical penthouse, glazed about 2019 but kept as the 2013 photograph shows it, under a flat roof at the Skyscraper Center's and Emporis's 350 ft. Its east end fills the gap between 340 on the Park and The Buckingham, where the drawing's buckingham-west group paints an office tower whose top stands about 140 layer units higher.", "footprint": { "way": 95486958, "version": 12, "coordinates": [[-87.6204966, 41.8869542], [-87.6202534, 41.8869566], [-87.6200384, 41.8869571], [-87.6200396, 41.887005], [-87.6200455, 41.8873733], [-87.620058, 41.8876286], [-87.6205101, 41.8876189], [-87.6205054, 41.8873683]] }, "parts": [{ "way": 95486958, "version": 12, "coordinates": [[-87.6204966, 41.8869542], [-87.6202534, 41.8869566], [-87.6200384, 41.8869571], [-87.6200396, 41.887005], [-87.6200455, 41.8873733], [-87.620058, 41.8876286], [-87.6205101, 41.8876189], [-87.6205054, 41.8873683]], "bottom": 0, "top": 106.7 }] },
49
- { "id": "building-swissotel", "name": "Swissôtel Chicago", "shortName": "Swissôtel", "height": 139.3, "tipHeight": 139.3, "heightSource": "https://www.skyscrapercenter.com/building/swissotel-chicago/4362", "note": "Detailed Swissôtel Chicago: the hotel's mapped tower part, a triangle; a flush grid of reflective glass, thin mullions about 1.5 m apart and a transom at each of OpenStreetMap's 45 levels, under a flat roof at the Skyscraper Center's 139.3 m. It stands behind Three Illinois Center and The Buckingham from the drawing's camera, and fills the seam where their corners meet. The hotel's outline, 95486966, adds a small block on the tower's north-east face, and its podium, 95486953, carries no height; neither is modelled.", "footprint": { "way": 641288601, "version": 3, "coordinates": [[-87.6194102, 41.8874254], [-87.619534, 41.8875706], [-87.619676, 41.8873866], [-87.6198184, 41.8871906], [-87.6192311, 41.8871971], [-87.619375, 41.8873843]] }, "parts": [{ "way": 641288601, "version": 3, "coordinates": [[-87.6194102, 41.8874254], [-87.619534, 41.8875706], [-87.619676, 41.8873866], [-87.6198184, 41.8871906], [-87.6192311, 41.8871971], [-87.619375, 41.8873843]], "bottom": 0, "top": 139.3 }] },
49
+ { "id": "building-swissotel", "name": "Swissôtel Chicago", "shortName": "Swissôtel", "height": 139.3, "tipHeight": 139.3, "heightSource": "https://www.skyscrapercenter.com/building/swissotel-chicago/4362", "note": "Detailed Swissôtel Chicago: the hotel's mapped tower part, a triangle; a flush grid of reflective vision windows above pale opaque floor bands, with thin mullions about 1.5 m apart and paired transoms in each of 45 retained modules. The bands take about 45% of each module from 2012 photographic ratios; precise occupied-floor and mechanical-row counts remain unresolved. The flat roof stays at the Skyscraper Center's 139.3 m. It stands behind Three Illinois Center and The Buckingham from the drawing's camera, and fills the seam where their corners meet. The hotel's outline, 95486966, adds a small block on the tower's north-east face, and its podium, 95486953, carries no height; neither is modelled.", "footprint": { "way": 641288601, "version": 3, "coordinates": [[-87.6194102, 41.8874254], [-87.619534, 41.8875706], [-87.619676, 41.8873866], [-87.6198184, 41.8871906], [-87.6192311, 41.8871971], [-87.619375, 41.8873843]] }, "parts": [{ "way": 641288601, "version": 3, "coordinates": [[-87.6194102, 41.8874254], [-87.619534, 41.8875706], [-87.619676, 41.8873866], [-87.6198184, 41.8871906], [-87.6192311, 41.8871971], [-87.619375, 41.8873843]], "bottom": 0, "top": 139.3 }] },
50
50
  ];
51
51
  // Every vehicular street on the upper or surface level across the 3D skyline's ground, from
52
52
  // a separate extract retrieved 2026-09-30: OpenStreetMap's roads and their links, and its
@@ -4,6 +4,7 @@ export declare const swissotelLevels: Readonly<{
4
4
  levels: 45;
5
5
  roof: 139.3;
6
6
  module: 1.5;
7
+ spandrel: 1.4;
7
8
  frame: 0.06;
8
9
  coping: 0.1;
9
10
  }>;
@@ -12,11 +13,12 @@ export declare const swissotelPalette: Readonly<{
12
13
  lit: 8882055;
13
14
  dim: 5329233;
14
15
  frame: 4276545;
16
+ spandrel: 9474192;
15
17
  }>;
16
18
  type Row = {
17
19
  lo: number;
18
20
  hi: number;
19
- kind: "glass" | "frame";
21
+ kind: "glass" | "frame" | "spandrel";
20
22
  floor: number;
21
23
  };
22
24
  export declare const swissotelRows: Row[];
@@ -7,24 +7,27 @@ import { chainSkin, chainsOf, orient, paintedSlab, planOf, turnsAt } from "./fac
7
7
  // the seam where their corners meet.
8
8
  //
9
9
  // A triangular tower of reflective glass: a flush grid of thin mullions about 1.5 m apart and
10
- // a transom at each floor, a panel to a floor, under a flat roof at the published 139.3 m. The
10
+ // paired opaque spandrel / vision panels at each floor, under a flat roof at the published 139.3 m. The
11
11
  // floors divide that height by OpenStreetMap's 45 levels. See docs/swissotel-reference.md.
12
12
  // Units are meters; +x is east, +z is south.
13
13
  export const swissotelLevels = Object.freeze({
14
- levels: 45, // OpenStreetMap's count, a panel to each
14
+ levels: 45, // retained module count; OSM and Enclos both report 45 storeys
15
15
  roof: 139.3, // the published height, the Skyscraper Center's 457 ft
16
16
  module: 1.5, // the mullions' spacing, read on the photographs
17
+ spandrel: 1.4, // about 45% of the retained floor pitch; 2012 photographs, ±0.2 m
17
18
  frame: 0.06, // each mullion's and transom's width
18
19
  coping: 0.1, // the roof's coping over the top panel
19
20
  });
20
21
  const h = swissotelLevels;
21
22
  const pitch = h.roof / h.levels;
22
- // The skins' colours: the window tones, and the frame, which no window shares.
23
- export const swissotelPalette = Object.freeze({ glass: [0x2d2d2d, 0x313131, 0x353535, 0x292929], lit: 0x878787, dim: 0x515151, frame: 0x414141 });
23
+ // Window tones are distinct from frames and opaque spandrels. The pale band
24
+ // is an explicit grey fallback, not a calibrated sunny-day colour.
25
+ export const swissotelPalette = Object.freeze({ glass: [0x2d2d2d, 0x313131, 0x353535, 0x292929], lit: 0x878787, dim: 0x515151, frame: 0x414141, spandrel: 0x909090 });
24
26
  const palette = swissotelPalette;
25
27
  const color = (hex) => new THREE.Color(hex);
26
28
  const glassTones = palette.glass.map(color);
27
29
  const litGlass = color(palette.lit), dimGlass = color(palette.dim), frame = color(palette.frame);
30
+ const spandrel = color(palette.spandrel);
28
31
  const core = color(0x1e1e1e), roofing = color(0x323232);
29
32
  function paneColor(row, bay, wall) {
30
33
  const hash = (Math.imul(row + 71, 0x9e3779b1) ^ Math.imul(bay + 13, 0x85ebca77) ^ Math.imul(wall + 47, 0xc2b2ae3d)) >>> 0;
@@ -38,7 +41,10 @@ function paneColor(row, bay, wall) {
38
41
  export const swissotelRows = [];
39
42
  for (let n = 1; n <= h.levels; n += 1) {
40
43
  const lo = n === 1 ? 0.25 : (n - 1) * pitch + h.frame / 2, hi = n === h.levels ? h.roof - h.coping : n * pitch - h.frame / 2;
41
- swissotelRows.push({ lo, hi, kind: "glass", floor: n });
44
+ const split = (n - 1) * pitch + h.spandrel;
45
+ swissotelRows.push({ lo, hi: split - h.frame / 2, kind: "spandrel", floor: n });
46
+ swissotelRows.push({ lo: split - h.frame / 2, hi: split + h.frame / 2, kind: "frame", floor: n });
47
+ swissotelRows.push({ lo: split + h.frame / 2, hi, kind: "glass", floor: n });
42
48
  swissotelRows.push({ lo: hi, hi: n === h.levels ? h.roof : n * pitch + h.frame / 2, kind: "frame", floor: n });
43
49
  }
44
50
  const rows = swissotelRows;
@@ -68,6 +74,8 @@ export function createSwissotelGeographicBuilding(record, projectPlan, offset) {
68
74
  const row = rows[r], middle = (columns[bay - 1] + columns[bay]) / 2;
69
75
  if (row.kind === "frame" || lines.some((c) => Math.abs(middle - c) < h.frame / 2))
70
76
  return frame;
77
+ if (row.kind === "spandrel")
78
+ return spandrel;
71
79
  return paneColor(row.floor, bay, index);
72
80
  }, frame);
73
81
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a2f0/skyline",
3
- "version": "0.2.29",
3
+ "version": "0.2.30",
4
4
  "description": "Interactive Chicago skyline viewer and reusable Three.js building models",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
@@ -263,7 +263,7 @@ export const colourMaterials = {
263
263
  // Reflective blue-green glass in its frame.
264
264
  "building-swissotel": {
265
265
  shell: ["neutral"],
266
- "curtain wall": ["blue-green glass", windows(0x878787, 0x515151)],
266
+ "curtain wall": ["blue-green glass", { ...windows(0x878787, 0x515151), 0x414141: "aluminium", 0x909090: "opaque spandrel" }],
267
267
  },
268
268
  };
269
269
  // A batch's materials from its mesh's name, if the trial knows the building and the batch.
@@ -204,6 +204,9 @@ export const measuredColours = {
204
204
  // docs/swissotel-reference.md, 2026-10-10 — Daytime colours from Chicago.jpg.
205
205
  "building-swissotel": {
206
206
  ...glass(0x475056, "blue-green glass"),
207
+ // FID-SWI-002: mixed panorama sample does not resolve these separately.
208
+ "opaque spandrel": null,
209
+ aluminium: null,
207
210
  neutral: null,
208
211
  },
209
212
  // docs/north-michigan-180-reference.md, 2026-10-10 — Daytime colours from Chicago.jpg. Only the
@@ -46,7 +46,7 @@ export const geographicBuildings = [
46
46
  { "id": "building-hyatt-regency-west-tower", "name": "Hyatt Regency Chicago West Tower", "shortName": "Hyatt West Tower", "height": 111.3, "tipHeight": 111.3, "heightSource": "https://www.skyscrapercenter.com/building/hyatt-regency-chicago-west-tower/13132", "note": "Detailed Hyatt Regency Chicago West Tower: its mapped part of the hotel's outline; a brick slab of 33 storeys, narrow window slots continuous from the lobby to the top two floors on a 3.5 m module between solid corners, and a plain band over them to a flat roof at the Skyscraper Center's 111.3 m. From the photograph's camera it stands between Aon Center and the Blue Cross and Blue Shield Tower, where the drawing's Blue Cross group paints a dark brown sliver.", "footprint": { "way": 235920252, "version": 4, "coordinates": [[-87.6227574, 41.887587], [-87.6228537, 41.887584], [-87.6228521, 41.8874603], [-87.6228518, 41.8874165], [-87.6225427, 41.8874231], [-87.6225408, 41.8875106], [-87.6225253, 41.8875109], [-87.6225266, 41.8875277], [-87.6225277, 41.8875513], [-87.622528, 41.8875746], [-87.6225382, 41.8878947], [-87.62255, 41.8878954], [-87.6225496, 41.8879846], [-87.6228658, 41.8879789], [-87.6228643, 41.8879388], [-87.6228611, 41.8878099], [-87.6227664, 41.8878103]] }, "parts": [{ "way": 235920252, "version": 4, "coordinates": [[-87.6227574, 41.887587], [-87.6228537, 41.887584], [-87.6228521, 41.8874603], [-87.6228518, 41.8874165], [-87.6225427, 41.8874231], [-87.6225408, 41.8875106], [-87.6225253, 41.8875109], [-87.6225266, 41.8875277], [-87.6225277, 41.8875513], [-87.622528, 41.8875746], [-87.6225382, 41.8878947], [-87.62255, 41.8878954], [-87.6225496, 41.8879846], [-87.6228658, 41.8879789], [-87.6228643, 41.8879388], [-87.6228611, 41.8878099], [-87.6227664, 41.8878103]], "bottom": 0, "top": 111.3 }] },
47
47
  { "id": "building-buckingham-east", "name": "Sheraton Grand Chicago Riverwalk", "shortName": "Sheraton Grand", "height": 112.3, "tipHeight": 112.3, "heightSource": "https://www.skyscrapercenter.com/building/sheraton-chicago-hotel-towers/10020", "note": "Detailed Sheraton Grand Chicago Riverwalk: the mapped tower and its corner part; a cream precast tower on an L of punched windows at Emporis's 2.67 m floor-to-floor, its arms to 94.76 m, the corner's round tower two floors higher to 100.1 m, and pale stepped frames under dark louvered screens on all four round ends, with the smaller bases approximated from the principal frame. The main crown reaches the Skyscraper Center's 112.3 m. Heights stand on the Skyscraper Center's datum: its top floor at 97 m, a floor-to-roof of 3.1 m and a 12.2 m main crown from Emporis; photographic ratios estimate about 7.2 m crowns on the arms and 6 m on the east wing; the published height nearest the drawing's reading, over Emporis's 330.56 ft. The Skyscraper Center's 112.8 m tip, 50 cm over the drum, is not modelled. The drawing's buckingham-east group is its corner's lit drum over its tower. The mapped east wing and its round end continue the hotel to the east, with estimated roofs at 84.08 m and 86.75 m on the same height datum and a fourth crown. Photographs from before 2013 establish the wing; exact roof and crown dimensions remain inferred.", "footprint": { "way": 592122464, "version": 5, "coordinates": [[-87.6199499, 41.8891119], [-87.6199176, 41.8893381], [-87.6199306, 41.8893589], [-87.6199502, 41.8893716], [-87.6199845, 41.8893878], [-87.6200276, 41.8893957], [-87.6200732, 41.8893915], [-87.6201147, 41.8893744], [-87.6201372, 41.8893482], [-87.6201463, 41.8893162], [-87.6201584, 41.8892447], [-87.6201841, 41.889063], [-87.6201875, 41.8890302], [-87.6201812, 41.8889946], [-87.6201588, 41.8889641], [-87.620121, 41.8889384], [-87.6200743, 41.8889276], [-87.6196505, 41.8888958], [-87.6196025, 41.8889162], [-87.6195726, 41.8889427], [-87.6195591, 41.8889735], [-87.6195627, 41.8890068], [-87.6195846, 41.8890373], [-87.6196228, 41.8890638], [-87.6198263, 41.8890777], [-87.6198225, 41.889104]] }, "parts": [{ "way": 592122464, "version": 5, "coordinates": [[-87.6199499, 41.8891119], [-87.6199176, 41.8893381], [-87.6199306, 41.8893589], [-87.6199502, 41.8893716], [-87.6199845, 41.8893878], [-87.6200276, 41.8893957], [-87.6200732, 41.8893915], [-87.6201147, 41.8893744], [-87.6201372, 41.8893482], [-87.6201463, 41.8893162], [-87.6201584, 41.8892447], [-87.6201841, 41.889063], [-87.6201875, 41.8890302], [-87.6201812, 41.8889946], [-87.6201588, 41.8889641], [-87.620121, 41.8889384], [-87.6200743, 41.8889276], [-87.6196505, 41.8888958], [-87.6196025, 41.8889162], [-87.6195726, 41.8889427], [-87.6195591, 41.8889735], [-87.6195627, 41.8890068], [-87.6195846, 41.8890373], [-87.6196228, 41.8890638], [-87.6198263, 41.8890777], [-87.6198225, 41.889104]], "bottom": 0, "top": 94.76 }, { "way": 1269924307, "version": 1, "coordinates": [[-87.6199691, 41.8890378], [-87.6199677, 41.889013], [-87.6199719, 41.8889952], [-87.6199903, 41.8889744], [-87.6200135, 41.88896], [-87.6200416, 41.8889517], [-87.6200717, 41.8889503], [-87.6201037, 41.8889568], [-87.6201308, 41.8889711], [-87.6201498, 41.8889914], [-87.6201583, 41.8890152], [-87.6201555, 41.8890398], [-87.6201415, 41.8890622], [-87.6201241, 41.8890776], [-87.6200882, 41.8890904], [-87.6200552, 41.8890928], [-87.6200258, 41.8890875], [-87.6200001, 41.8890757], [-87.6199805, 41.8890586]], "bottom": 94.76, "top": 100.1 }, { "way": 1269924305, "version": 1, "coordinates": [[-87.6191033, 41.8890226], [-87.6190622, 41.8889954], [-87.6190428, 41.8889627], [-87.6190431, 41.8889236], [-87.6190607, 41.8888928], [-87.619091, 41.8888724], [-87.6191278, 41.8888566], [-87.6193634, 41.8888743], [-87.6196505, 41.8888958], [-87.6196025, 41.8889162], [-87.6195726, 41.8889427], [-87.6195591, 41.8889735], [-87.6195627, 41.8890068], [-87.6195846, 41.8890373], [-87.6196228, 41.8890638]], "bottom": 0, "top": 84.08, "estimatedHeight": true }, { "way": 1269924304, "version": 1, "coordinates": [[-87.619112, 41.8888866], [-87.61909, 41.8888996], [-87.6190746, 41.888917], [-87.6190672, 41.8889372], [-87.6190685, 41.8889581], [-87.6190786, 41.8889777], [-87.6190963, 41.8889939], [-87.6191199, 41.8890052], [-87.6191471, 41.8890105], [-87.6191778, 41.8890088], [-87.6192059, 41.8889994], [-87.619228, 41.8889835], [-87.6192416, 41.8889629], [-87.6192449, 41.8889401], [-87.6192376, 41.8889179], [-87.6192207, 41.8888988], [-87.6191959, 41.8888851], [-87.6191665, 41.8888785], [-87.6191384, 41.8888793]], "bottom": 84.08, "top": 86.75, "estimatedHeight": true }], "groundFootprintWays": [592122464, 1269924305] },
48
48
  { "id": "building-three-illinois-center", "name": "Three Illinois Center", "shortName": "Three Illinois Center", "height": 106.7, "tipHeight": 106.7, "heightSource": "https://www.skyscrapercenter.com/building/three-illinois-center/13913", "note": "Detailed Three Illinois Center: the mapped outline; a dark bronze curtain wall of 30 storeys, mullions on a 5 ft module and glass over a spandrel on each floor at the published 11.5 ft slab to slab over a 5.06 m lobby, and the top two floors' windowless mechanical penthouse, glazed about 2019 but kept as the 2013 photograph shows it, under a flat roof at the Skyscraper Center's and Emporis's 350 ft. Its east end fills the gap between 340 on the Park and The Buckingham, where the drawing's buckingham-west group paints an office tower whose top stands about 140 layer units higher.", "footprint": { "way": 95486958, "version": 12, "coordinates": [[-87.6204966, 41.8869542], [-87.6202534, 41.8869566], [-87.6200384, 41.8869571], [-87.6200396, 41.887005], [-87.6200455, 41.8873733], [-87.620058, 41.8876286], [-87.6205101, 41.8876189], [-87.6205054, 41.8873683]] }, "parts": [{ "way": 95486958, "version": 12, "coordinates": [[-87.6204966, 41.8869542], [-87.6202534, 41.8869566], [-87.6200384, 41.8869571], [-87.6200396, 41.887005], [-87.6200455, 41.8873733], [-87.620058, 41.8876286], [-87.6205101, 41.8876189], [-87.6205054, 41.8873683]], "bottom": 0, "top": 106.7 }] },
49
- { "id": "building-swissotel", "name": "Swissôtel Chicago", "shortName": "Swissôtel", "height": 139.3, "tipHeight": 139.3, "heightSource": "https://www.skyscrapercenter.com/building/swissotel-chicago/4362", "note": "Detailed Swissôtel Chicago: the hotel's mapped tower part, a triangle; a flush grid of reflective glass, thin mullions about 1.5 m apart and a transom at each of OpenStreetMap's 45 levels, under a flat roof at the Skyscraper Center's 139.3 m. It stands behind Three Illinois Center and The Buckingham from the drawing's camera, and fills the seam where their corners meet. The hotel's outline, 95486966, adds a small block on the tower's north-east face, and its podium, 95486953, carries no height; neither is modelled.", "footprint": { "way": 641288601, "version": 3, "coordinates": [[-87.6194102, 41.8874254], [-87.619534, 41.8875706], [-87.619676, 41.8873866], [-87.6198184, 41.8871906], [-87.6192311, 41.8871971], [-87.619375, 41.8873843]] }, "parts": [{ "way": 641288601, "version": 3, "coordinates": [[-87.6194102, 41.8874254], [-87.619534, 41.8875706], [-87.619676, 41.8873866], [-87.6198184, 41.8871906], [-87.6192311, 41.8871971], [-87.619375, 41.8873843]], "bottom": 0, "top": 139.3 }] },
49
+ { "id": "building-swissotel", "name": "Swissôtel Chicago", "shortName": "Swissôtel", "height": 139.3, "tipHeight": 139.3, "heightSource": "https://www.skyscrapercenter.com/building/swissotel-chicago/4362", "note": "Detailed Swissôtel Chicago: the hotel's mapped tower part, a triangle; a flush grid of reflective vision windows above pale opaque floor bands, with thin mullions about 1.5 m apart and paired transoms in each of 45 retained modules. The bands take about 45% of each module from 2012 photographic ratios; precise occupied-floor and mechanical-row counts remain unresolved. The flat roof stays at the Skyscraper Center's 139.3 m. It stands behind Three Illinois Center and The Buckingham from the drawing's camera, and fills the seam where their corners meet. The hotel's outline, 95486966, adds a small block on the tower's north-east face, and its podium, 95486953, carries no height; neither is modelled.", "footprint": { "way": 641288601, "version": 3, "coordinates": [[-87.6194102, 41.8874254], [-87.619534, 41.8875706], [-87.619676, 41.8873866], [-87.6198184, 41.8871906], [-87.6192311, 41.8871971], [-87.619375, 41.8873843]] }, "parts": [{ "way": 641288601, "version": 3, "coordinates": [[-87.6194102, 41.8874254], [-87.619534, 41.8875706], [-87.619676, 41.8873866], [-87.6198184, 41.8871906], [-87.6192311, 41.8871971], [-87.619375, 41.8873843]], "bottom": 0, "top": 139.3 }] },
50
50
  ];
51
51
  // Every vehicular street on the upper or surface level across the 3D skyline's ground, from
52
52
  // a separate extract retrieved 2026-09-30: OpenStreetMap's roads and their links, and its
@@ -7,24 +7,27 @@ import { chainSkin, chainsOf, orient, paintedSlab, planOf, turnsAt } from "./fac
7
7
  // the seam where their corners meet.
8
8
  //
9
9
  // A triangular tower of reflective glass: a flush grid of thin mullions about 1.5 m apart and
10
- // a transom at each floor, a panel to a floor, under a flat roof at the published 139.3 m. The
10
+ // paired opaque spandrel / vision panels at each floor, under a flat roof at the published 139.3 m. The
11
11
  // floors divide that height by OpenStreetMap's 45 levels. See docs/swissotel-reference.md.
12
12
  // Units are meters; +x is east, +z is south.
13
13
  export const swissotelLevels = Object.freeze({
14
- levels: 45, // OpenStreetMap's count, a panel to each
14
+ levels: 45, // retained module count; OSM and Enclos both report 45 storeys
15
15
  roof: 139.3, // the published height, the Skyscraper Center's 457 ft
16
16
  module: 1.5, // the mullions' spacing, read on the photographs
17
+ spandrel: 1.4, // about 45% of the retained floor pitch; 2012 photographs, ±0.2 m
17
18
  frame: 0.06, // each mullion's and transom's width
18
19
  coping: 0.1, // the roof's coping over the top panel
19
20
  });
20
21
  const h = swissotelLevels;
21
22
  const pitch = h.roof / h.levels;
22
- // The skins' colours: the window tones, and the frame, which no window shares.
23
- export const swissotelPalette = Object.freeze({ glass: [0x2d2d2d, 0x313131, 0x353535, 0x292929], lit: 0x878787, dim: 0x515151, frame: 0x414141 });
23
+ // Window tones are distinct from frames and opaque spandrels. The pale band
24
+ // is an explicit grey fallback, not a calibrated sunny-day colour.
25
+ export const swissotelPalette = Object.freeze({ glass: [0x2d2d2d, 0x313131, 0x353535, 0x292929], lit: 0x878787, dim: 0x515151, frame: 0x414141, spandrel: 0x909090 });
24
26
  const palette = swissotelPalette;
25
27
  const color = (hex) => new THREE.Color(hex);
26
28
  const glassTones = palette.glass.map(color);
27
29
  const litGlass = color(palette.lit), dimGlass = color(palette.dim), frame = color(palette.frame);
30
+ const spandrel = color(palette.spandrel);
28
31
  const core = color(0x1e1e1e), roofing = color(0x323232);
29
32
  function paneColor(row, bay, wall) {
30
33
  const hash = (Math.imul(row + 71, 0x9e3779b1) ^ Math.imul(bay + 13, 0x85ebca77) ^ Math.imul(wall + 47, 0xc2b2ae3d)) >>> 0;
@@ -38,7 +41,10 @@ function paneColor(row, bay, wall) {
38
41
  export const swissotelRows = [];
39
42
  for (let n = 1; n <= h.levels; n += 1) {
40
43
  const lo = n === 1 ? 0.25 : (n - 1) * pitch + h.frame / 2, hi = n === h.levels ? h.roof - h.coping : n * pitch - h.frame / 2;
41
- swissotelRows.push({ lo, hi, kind: "glass", floor: n });
44
+ const split = (n - 1) * pitch + h.spandrel;
45
+ swissotelRows.push({ lo, hi: split - h.frame / 2, kind: "spandrel", floor: n });
46
+ swissotelRows.push({ lo: split - h.frame / 2, hi: split + h.frame / 2, kind: "frame", floor: n });
47
+ swissotelRows.push({ lo: split + h.frame / 2, hi, kind: "glass", floor: n });
42
48
  swissotelRows.push({ lo: hi, hi: n === h.levels ? h.roof : n * pitch + h.frame / 2, kind: "frame", floor: n });
43
49
  }
44
50
  const rows = swissotelRows;
@@ -68,6 +74,8 @@ export function createSwissotelGeographicBuilding(record, projectPlan, offset) {
68
74
  const row = rows[r], middle = (columns[bay - 1] + columns[bay]) / 2;
69
75
  if (row.kind === "frame" || lines.some((c) => Math.abs(middle - c) < h.frame / 2))
70
76
  return frame;
77
+ if (row.kind === "spandrel")
78
+ return spandrel;
71
79
  return paneColor(row.floor, bay, index);
72
80
  }, frame);
73
81
  });