@seatlayer/core 0.52.0 → 0.54.0

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.
Files changed (110) hide show
  1. package/LICENSE +16 -17
  2. package/README.md +8 -18
  3. package/dist/categoryInventory-B4xo7hE2.d.ts +109 -0
  4. package/dist/categoryInventory-lRtu3VjD.d.cts +109 -0
  5. package/dist/chunk-3QLFGEQY.js +1 -0
  6. package/dist/chunk-55NOSZK5.js +1 -0
  7. package/dist/chunk-6LIPQU4G.js +1 -0
  8. package/dist/chunk-6VTTBC5F.js +1 -0
  9. package/dist/chunk-7PT7OQUO.js +1 -0
  10. package/dist/chunk-AQKYUJBX.js +1 -0
  11. package/dist/chunk-CXF32VPG.js +1 -0
  12. package/dist/chunk-DDE7IOFT.js +1 -0
  13. package/dist/chunk-EQM4FFN5.js +1 -0
  14. package/dist/chunk-EYROIZGQ.js +1 -0
  15. package/dist/chunk-IJI4WU57.js +1 -0
  16. package/dist/chunk-QUKWJQLR.js +1 -0
  17. package/dist/chunk-VDZ24QVV.js +1 -0
  18. package/dist/chunk-XPPT3OGQ.js +1 -0
  19. package/dist/core/chart-ops/index.cjs +1 -0
  20. package/dist/core/chart-ops/index.d.cts +1235 -0
  21. package/dist/core/chart-ops/index.d.ts +1235 -0
  22. package/dist/core/chart-ops/index.js +1 -0
  23. package/dist/core/color.cjs +1 -0
  24. package/dist/core/color.d.cts +192 -0
  25. package/dist/core/color.d.ts +192 -0
  26. package/dist/core/color.js +1 -0
  27. package/dist/core/inventory/index.cjs +1 -0
  28. package/dist/core/inventory/index.d.cts +209 -0
  29. package/dist/core/inventory/index.d.ts +209 -0
  30. package/dist/core/inventory/index.js +1 -0
  31. package/dist/core/layout/index.cjs +1 -0
  32. package/dist/core/layout/index.d.cts +376 -0
  33. package/dist/core/layout/index.d.ts +376 -0
  34. package/dist/core/layout/index.js +1 -0
  35. package/dist/core/quality/index.cjs +1 -0
  36. package/dist/core/quality/index.d.cts +132 -0
  37. package/dist/core/quality/index.d.ts +132 -0
  38. package/dist/core/quality/index.js +1 -0
  39. package/dist/core/render-assets/index.cjs +1 -0
  40. package/dist/core/render-assets/index.d.cts +99 -0
  41. package/dist/core/render-assets/index.d.ts +99 -0
  42. package/dist/core/render-assets/index.js +1 -0
  43. package/dist/core/seatConfidence.cjs +1 -76
  44. package/dist/core/seatConfidence.d.cts +1 -1
  45. package/dist/core/seatConfidence.d.ts +1 -1
  46. package/dist/core/seatConfidence.js +1 -51
  47. package/dist/core/sections/index.cjs +1 -0
  48. package/dist/core/sections/index.d.cts +346 -0
  49. package/dist/core/sections/index.d.ts +346 -0
  50. package/dist/core/sections/index.js +1 -0
  51. package/dist/de-75NWRKC5.js +1 -0
  52. package/dist/es-BM7EJ7PW.js +1 -0
  53. package/dist/fr-HPXQHIB4.js +1 -0
  54. package/dist/index.cjs +1 -12717
  55. package/dist/index.d.cts +71 -580
  56. package/dist/index.d.ts +71 -580
  57. package/dist/index.js +1 -10235
  58. package/dist/labeling-CsPt1mC_.d.cts +90 -0
  59. package/dist/labeling-w8bl86cb.d.ts +90 -0
  60. package/dist/layout-B5UYbwnv.d.ts +181 -0
  61. package/dist/layout-YFmuxw_M.d.cts +181 -0
  62. package/dist/picker/minimapGeometry.cjs +1 -80
  63. package/dist/picker/minimapGeometry.js +1 -52
  64. package/dist/renderedQuality-CugJarFp.d.cts +113 -0
  65. package/dist/renderedQuality-DbZM034G.d.ts +113 -0
  66. package/dist/renderer-DhUHFtsI.d.cts +531 -0
  67. package/dist/renderer-IBi9YKWR.d.ts +531 -0
  68. package/dist/sections-B7cDF0Nq.d.cts +123 -0
  69. package/dist/sections-mLOZrGrI.d.ts +123 -0
  70. package/dist/segmentedRowModel-BPTnJ7Tz.d.ts +75 -0
  71. package/dist/segmentedRowModel-CGoH684F.d.cts +75 -0
  72. package/dist/ticketRestrictions-BwAebpSK.d.cts +72 -0
  73. package/dist/ticketRestrictions-ChHJwvTq.d.ts +72 -0
  74. package/dist/{types-tLOunI-B.d.cts → types-COfJorq_.d.cts} +233 -757
  75. package/dist/{types-tLOunI-B.d.ts → types-COfJorq_.d.ts} +233 -757
  76. package/dist/view/panoramaDelivery.cjs +1 -126
  77. package/dist/view/panoramaDelivery.js +1 -17
  78. package/dist/view3d/crossfade/panorama.cjs +1 -459
  79. package/dist/view3d/crossfade/panorama.d.cts +2 -4
  80. package/dist/view3d/crossfade/panorama.d.ts +2 -4
  81. package/dist/view3d/crossfade/panorama.js +1 -30
  82. package/dist/view3d/index.cjs +27 -7929
  83. package/dist/view3d/index.d.cts +64 -22
  84. package/dist/view3d/index.d.ts +64 -22
  85. package/dist/view3d/index.js +27 -7062
  86. package/package.json +95 -11
  87. package/dist/chunk-AZODENEL.js +0 -97
  88. package/dist/chunk-AZODENEL.js.map +0 -1
  89. package/dist/chunk-BE3F7CT3.js +0 -341
  90. package/dist/chunk-BE3F7CT3.js.map +0 -1
  91. package/dist/chunk-UID7KN44.js +0 -1569
  92. package/dist/chunk-UID7KN44.js.map +0 -1
  93. package/dist/core/seatConfidence.cjs.map +0 -1
  94. package/dist/core/seatConfidence.js.map +0 -1
  95. package/dist/de-YGODYJ3E.js +0 -292
  96. package/dist/de-YGODYJ3E.js.map +0 -1
  97. package/dist/es-VMBTGVFQ.js +0 -292
  98. package/dist/es-VMBTGVFQ.js.map +0 -1
  99. package/dist/fr-SLBE2ULB.js +0 -292
  100. package/dist/fr-SLBE2ULB.js.map +0 -1
  101. package/dist/index.cjs.map +0 -1
  102. package/dist/index.js.map +0 -1
  103. package/dist/picker/minimapGeometry.cjs.map +0 -1
  104. package/dist/picker/minimapGeometry.js.map +0 -1
  105. package/dist/view/panoramaDelivery.cjs.map +0 -1
  106. package/dist/view/panoramaDelivery.js.map +0 -1
  107. package/dist/view3d/crossfade/panorama.cjs.map +0 -1
  108. package/dist/view3d/crossfade/panorama.js.map +0 -1
  109. package/dist/view3d/index.cjs.map +0 -1
  110. package/dist/view3d/index.js.map +0 -1
@@ -1,1569 +0,0 @@
1
- // src/core/types.ts
2
- var ACCESSIBILITY_TYPES = [
3
- { key: "wheelchair", label: "Wheelchair space", short: "Wheelchair", icon: "\u267F" },
4
- { key: "companion", label: "Companion seat", short: "Companion", icon: "\u{1F9D1}\u200D\u{1F91D}\u200D\u{1F9D1}" },
5
- { key: "semi-ambulatory", label: "Semi-ambulatory (limited mobility)", short: "Limited mobility", icon: "\u{1F9AF}" },
6
- { key: "hearing", label: "Assistive listening", short: "Hearing", icon: "\u{1F9BB}" },
7
- { key: "cart", label: "CART live-caption view", short: "CART captions", icon: "CC" },
8
- { key: "sign-language", label: "Sign-language view", short: "Sign language", icon: "\u{1F91F}" },
9
- { key: "plus-size", label: "Plus-size seat", short: "Plus-size", icon: "\u{1F4BA}" },
10
- { key: "lift-armrest", label: "Lift-up armrest", short: "Lift armrest", icon: "\u2195\uFE0F" }
11
- ];
12
- var ACCESSIBILITY_LABEL = new Map(ACCESSIBILITY_TYPES.map((a) => [a.key, a]));
13
- function accessibilityMeta(key) {
14
- return ACCESSIBILITY_LABEL.get(key);
15
- }
16
- var ACCESSIBILITY_RING_COLOR = {
17
- wheelchair: "#3b82f6",
18
- companion: "#8b5cf6",
19
- "semi-ambulatory": "#0ea5e9",
20
- hearing: "#14b8a6",
21
- cart: "#7c3aed",
22
- "sign-language": "#f59e0b",
23
- "plus-size": "#ec4899",
24
- "lift-armrest": "#22c55e"
25
- };
26
- function accessibilityRingColor(types) {
27
- const primary = types?.[0];
28
- return primary && ACCESSIBILITY_RING_COLOR[primary] || "#3b82f6";
29
- }
30
- var SEAT_COMMERCIAL_MARKS = [
31
- { key: "obstructedView", label: "Obstructed view", short: "Obstructed", icon: "\u26D4" },
32
- { key: "restrictedView", label: "Restricted view", short: "Restricted", icon: "\u{1F441}" },
33
- { key: "premium", label: "Premium seat", short: "Premium", icon: "\u2605" }
34
- ];
35
- var SEAT_COMMERCIAL_LABEL = new Map(SEAT_COMMERCIAL_MARKS.map((mark) => [mark.key, mark]));
36
- function seatCommercialMeta(key) {
37
- return SEAT_COMMERCIAL_LABEL.get(key);
38
- }
39
- var LABEL_STYLE_MIN_SIZE = 8;
40
- var LABEL_STYLE_MAX_SIZE = 24;
41
- var SURROUNDINGS_SHAPE_ROLES = [
42
- "reference-focal",
43
- "bar",
44
- "entrance",
45
- "exit",
46
- "restroom",
47
- "screen",
48
- "sound",
49
- "concession",
50
- "coat",
51
- "wall",
52
- "rail",
53
- "suite",
54
- "obstruction"
55
- ];
56
- var SURROUNDINGS_SHAPE_ROLE_SET = new Set(SURROUNDINGS_SHAPE_ROLES);
57
- function layerOf(obj) {
58
- switch (obj.type) {
59
- case "row":
60
- case "table":
61
- case "gaArea":
62
- case "booth":
63
- case "section":
64
- return "interactive";
65
- // Raster décor follows its explicit authored z-layer. Absence retains the
66
- // legacy Background default; bitmap content is never guessed semantically.
67
- case "decorImage":
68
- return obj.layer === "foreground" ? "foreground" : "background";
69
- // Source-backed focal geometry and curated venue landmarks help an author
70
- // orient around the sellable plan. A stage and an ordinary authored shape
71
- // remain Background even when they carry an arbitrary/custom role.
72
- case "shape":
73
- return obj.role && SURROUNDINGS_SHAPE_ROLE_SET.has(obj.role) ? "surroundings" : "background";
74
- // Free text — including semantic icon text — is background furniture.
75
- case "text":
76
- return "background";
77
- default:
78
- return "interactive";
79
- }
80
- }
81
- var CHART_STORAGE_KEY = "seatmap.chart";
82
-
83
- // src/core/units.ts
84
- var METRES_PER_CHART_UNIT = 0.55 / 24;
85
- var CHART_UNITS_PER_METRE = 1 / METRES_PER_CHART_UNIT;
86
- var LIFT_PER_STEP_WORLD = 58;
87
- var TIER_HEIGHT_M = LIFT_PER_STEP_WORLD * METRES_PER_CHART_UNIT;
88
- var SECTION_ELEVATION_TIER_MIN = 0;
89
- var SECTION_ELEVATION_TIER_MAX = 3;
90
- var SECTION_HEIGHT_MIN_M = 0;
91
- var SECTION_HEIGHT_MAX_M = 120;
92
- var SECTION_RAKE_MIN_DEG = 0;
93
- var SECTION_RAKE_MAX_DEG = 45;
94
- var LEGACY_SECTION_ELEVATION_TIER_MAX = 7;
95
- var SEATED_EYE_HEIGHT_M = 1.2;
96
- function finiteClamped(value, min, max, fallback) {
97
- return Number.isFinite(value) ? Math.max(min, Math.min(max, value)) : fallback;
98
- }
99
- function sectionElevationTier(value) {
100
- if (!Number.isFinite(value)) return SECTION_ELEVATION_TIER_MIN;
101
- return Math.max(
102
- SECTION_ELEVATION_TIER_MIN,
103
- Math.min(SECTION_ELEVATION_TIER_MAX, Math.round(value))
104
- );
105
- }
106
- function compatibleAutomaticTier(value) {
107
- if (!Number.isFinite(value) || !Number.isInteger(value) || value < 0) return 0;
108
- if (value <= LEGACY_SECTION_ELEVATION_TIER_MAX) return value;
109
- return SECTION_ELEVATION_TIER_MAX;
110
- }
111
- function sectionGeometry(section, context = {}) {
112
- const floorBaseHeightM = finiteClamped(
113
- context.floorBaseHeightM,
114
- SECTION_HEIGHT_MIN_M,
115
- SECTION_HEIGHT_MAX_M,
116
- 0
117
- );
118
- const automaticHeight = Math.min(
119
- SECTION_HEIGHT_MAX_M,
120
- floorBaseHeightM + compatibleAutomaticTier(section.elevation) * TIER_HEIGHT_M
121
- );
122
- const height = section.height === void 0 ? automaticHeight : finiteClamped(section.height, SECTION_HEIGHT_MIN_M, SECTION_HEIGHT_MAX_M, automaticHeight);
123
- const rake = finiteClamped(section.rake, SECTION_RAKE_MIN_DEG, SECTION_RAKE_MAX_DEG, 0);
124
- return { height, rake };
125
- }
126
-
127
- // src/core/textLayout.ts
128
- var glyphAdvance = (text) => Math.max(1, text.fontSize * 0.6 + (text.letterSpacing ?? 0));
129
- function wrappedLineCount(text, usableWidth) {
130
- const explicit = text.text.split(/\r?\n/);
131
- if (!text.width) return Math.max(1, explicit.length);
132
- const perLine = Math.max(1, Math.floor(usableWidth / glyphAdvance(text)));
133
- let lines = 0;
134
- for (const source of explicit) {
135
- if (!source.length) {
136
- lines += 1;
137
- continue;
138
- }
139
- let used = 0;
140
- for (const word of source.split(/\s+/)) {
141
- const length = word.length;
142
- if (!used) {
143
- lines += Math.max(1, Math.ceil(length / perLine));
144
- used = length % perLine;
145
- } else if (used + 1 + length <= perLine) used += 1 + length;
146
- else {
147
- lines += Math.max(1, Math.ceil(length / perLine));
148
- used = length % perLine;
149
- }
150
- }
151
- }
152
- return Math.max(1, lines);
153
- }
154
- function textLayoutMetrics(text) {
155
- const padding = text.background?.padding ?? 0;
156
- const explicitLines = text.text.split(/\r?\n/);
157
- const naturalWidth = Math.max(1, ...explicitLines.map((line) => line.length)) * glyphAdvance(text);
158
- const width = text.width ?? naturalWidth + padding * 2;
159
- const usableWidth = Math.max(1, width - padding * 2);
160
- const lineCount = wrappedLineCount(text, usableWidth);
161
- return {
162
- width,
163
- height: lineCount * text.fontSize * (text.lineHeight ?? 1.2) + padding * 2,
164
- lineCount,
165
- padding
166
- };
167
- }
168
-
169
- // src/core/complexGeometry.ts
170
- function cubicPoint(path, t) {
171
- const u = 1 - t;
172
- const a = u * u * u;
173
- const b = 3 * u * u * t;
174
- const c = 3 * u * t * t;
175
- const d = t * t * t;
176
- return {
177
- x: a * path.start.x + b * path.control1.x + c * path.control2.x + d * path.end.x,
178
- y: a * path.start.y + b * path.control1.y + c * path.control2.y + d * path.end.y
179
- };
180
- }
181
- function distributeAlongCubic(path, count, resolution = 192) {
182
- if (!Number.isInteger(count) || count < 1) throw new Error("Path point count must be a positive integer");
183
- if (count === 1) return [cubicPoint(path, 0.5)];
184
- const samples = Array.from({ length: resolution + 1 }, (_, index) => cubicPoint(path, index / resolution));
185
- const lengths = new Float64Array(samples.length);
186
- for (let index = 1; index < samples.length; index += 1) {
187
- const dx = samples[index].x - samples[index - 1].x;
188
- const dy = samples[index].y - samples[index - 1].y;
189
- lengths[index] = lengths[index - 1] + Math.hypot(dx, dy);
190
- }
191
- const total = lengths[lengths.length - 1];
192
- if (total <= 1e-9) return Array.from({ length: count }, () => ({ ...path.start }));
193
- const output = [];
194
- let segment = 1;
195
- for (let index = 0; index < count; index += 1) {
196
- const target = total * index / (count - 1);
197
- while (segment < lengths.length - 1 && lengths[segment] < target) segment += 1;
198
- const before = lengths[segment - 1];
199
- const after = lengths[segment];
200
- const ratio = after === before ? 0 : (target - before) / (after - before);
201
- output.push({
202
- x: samples[segment - 1].x + (samples[segment].x - samples[segment - 1].x) * ratio,
203
- y: samples[segment - 1].y + (samples[segment].y - samples[segment - 1].y) * ratio
204
- });
205
- }
206
- return output;
207
- }
208
-
209
- // src/core/polygonAnchor.ts
210
- var MAX_CELLS = 4e3;
211
- function distanceToSegment(p, a, b) {
212
- const dx = b.x - a.x;
213
- const dy = b.y - a.y;
214
- const denominator = dx * dx + dy * dy;
215
- const t = denominator ? Math.max(0, Math.min(1, ((p.x - a.x) * dx + (p.y - a.y) * dy) / denominator)) : 0;
216
- return Math.hypot(p.x - (a.x + t * dx), p.y - (a.y + t * dy));
217
- }
218
- function distanceToRings(p, rings) {
219
- let best = Infinity;
220
- for (const ring of rings) {
221
- if (ring.length < 2) continue;
222
- for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {
223
- const d = distanceToSegment(p, ring[j], ring[i]);
224
- if (d < best) best = d;
225
- }
226
- }
227
- return best;
228
- }
229
- function inRing(p, ring) {
230
- let inside = false;
231
- for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {
232
- const xi = ring[i].x;
233
- const yi = ring[i].y;
234
- const xj = ring[j].x;
235
- const yj = ring[j].y;
236
- const hit = yi > p.y !== yj > p.y && p.x < (xj - xi) * (p.y - yi) / (yj - yi) + xi;
237
- if (hit) inside = !inside;
238
- }
239
- return inside;
240
- }
241
- function signedDistance(p, outer, holes) {
242
- const inside = inRing(p, outer) && !holes.some((hole) => inRing(p, hole));
243
- const distance = distanceToRings(p, [outer, ...holes]);
244
- return inside ? distance : -distance;
245
- }
246
- function cellAt(x, y, h, outer, holes) {
247
- const d = signedDistance({ x, y }, outer, holes);
248
- return { x, y, h, d, max: d + h * Math.SQRT2 };
249
- }
250
- var CellQueue = class {
251
- constructor() {
252
- this.items = [];
253
- }
254
- get size() {
255
- return this.items.length;
256
- }
257
- push(cell) {
258
- const items = this.items;
259
- items.push(cell);
260
- let index = items.length - 1;
261
- while (index > 0) {
262
- const parent = index - 1 >> 1;
263
- if (items[parent].max >= items[index].max) break;
264
- [items[parent], items[index]] = [items[index], items[parent]];
265
- index = parent;
266
- }
267
- }
268
- pop() {
269
- const items = this.items;
270
- const top = items[0];
271
- const last = items.pop();
272
- if (items.length && last) {
273
- items[0] = last;
274
- let index = 0;
275
- for (; ; ) {
276
- const left = index * 2 + 1;
277
- const right = left + 1;
278
- let best = index;
279
- if (left < items.length && items[left].max > items[best].max) best = left;
280
- if (right < items.length && items[right].max > items[best].max) best = right;
281
- if (best === index) break;
282
- [items[best], items[index]] = [items[index], items[best]];
283
- index = best;
284
- }
285
- }
286
- return top;
287
- }
288
- };
289
- function polygonArea(ring) {
290
- if (ring.length < 3) return 0;
291
- let sum = 0;
292
- for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {
293
- sum += (ring[j].x + ring[i].x) * (ring[j].y - ring[i].y);
294
- }
295
- return Math.abs(sum) / 2;
296
- }
297
- function polygonNetArea(outer, holes) {
298
- return Math.max(0, polygonArea(outer) - (holes ?? []).reduce((total, hole) => total + polygonArea(hole), 0));
299
- }
300
- function polygonInscribedAnchor(outer, holes) {
301
- const rings = holes ?? [];
302
- if (!outer.length) return { point: { x: 0, y: 0 }, radius: 0 };
303
- if (outer.length < 3) {
304
- const x = outer.reduce((total, p) => total + p.x, 0) / outer.length;
305
- const y = outer.reduce((total, p) => total + p.y, 0) / outer.length;
306
- return { point: { x, y }, radius: 0 };
307
- }
308
- let minX = Infinity;
309
- let minY = Infinity;
310
- let maxX = -Infinity;
311
- let maxY = -Infinity;
312
- for (const p of outer) {
313
- if (p.x < minX) minX = p.x;
314
- if (p.y < minY) minY = p.y;
315
- if (p.x > maxX) maxX = p.x;
316
- if (p.y > maxY) maxY = p.y;
317
- }
318
- const width = maxX - minX;
319
- const height = maxY - minY;
320
- const cellSize = Math.min(width, height);
321
- if (!(cellSize > 0)) {
322
- return { point: { x: (minX + maxX) / 2, y: (minY + maxY) / 2 }, radius: 0 };
323
- }
324
- const precision = Math.max(width, height) / 150;
325
- const queue = new CellQueue();
326
- let h = cellSize / 2;
327
- for (let x = minX; x < maxX; x += cellSize) {
328
- for (let y = minY; y < maxY; y += cellSize) {
329
- queue.push(cellAt(x + h, y + h, h, outer, rings));
330
- }
331
- }
332
- let best = cellAt(minX + width / 2, minY + height / 2, 0, outer, rings);
333
- let explored = 0;
334
- while (queue.size) {
335
- const cell = queue.pop();
336
- if (!cell) break;
337
- if (cell.d > best.d) best = cell;
338
- if (cell.max - best.d <= precision) continue;
339
- if (explored >= MAX_CELLS) continue;
340
- explored += 1;
341
- h = cell.h / 2;
342
- queue.push(cellAt(cell.x - h, cell.y - h, h, outer, rings));
343
- queue.push(cellAt(cell.x + h, cell.y - h, h, outer, rings));
344
- queue.push(cellAt(cell.x - h, cell.y + h, h, outer, rings));
345
- queue.push(cellAt(cell.x + h, cell.y + h, h, outer, rings));
346
- }
347
- return { point: { x: best.x, y: best.y }, radius: Math.max(0, best.d) };
348
- }
349
-
350
- // src/core/sectionPath.ts
351
- var TAU = Math.PI * 2;
352
- function translateSectionOutlinePath(path, dx, dy) {
353
- const translate = (point) => ({ x: point.x + dx, y: point.y + dy });
354
- return transformSectionOutlinePath(path, translate);
355
- }
356
- function transformSectionOutlinePath(path, transform, radiusScale = 1, reflected = false) {
357
- return {
358
- ...path,
359
- start: transform(path.start),
360
- segments: path.segments.map((segment) => segment.kind === "line" ? { ...segment, end: transform(segment.end) } : segment.kind === "arc" ? {
361
- ...segment,
362
- center: transform(segment.center),
363
- radius: segment.radius * Math.abs(radiusScale),
364
- clockwise: reflected ? !segment.clockwise : segment.clockwise,
365
- end: transform(segment.end)
366
- } : {
367
- ...segment,
368
- control1: transform(segment.control1),
369
- control2: transform(segment.control2),
370
- end: transform(segment.end)
371
- })
372
- };
373
- }
374
- var SAGITTA_TO_CONTROL = 4 / 3;
375
-
376
- // src/core/segmentedRowModel.ts
377
- function resolveSegmentedRowGroups(objects) {
378
- const segmented = /* @__PURE__ */ new Map();
379
- const grouped = /* @__PURE__ */ new Map();
380
- for (const object of objects) {
381
- if (object.type !== "row" || !object.segmentedRow) continue;
382
- const list = grouped.get(object.segmentedRow.groupId) ?? [];
383
- list.push(object);
384
- grouped.set(object.segmentedRow.groupId, list);
385
- }
386
- for (const [groupId, members] of grouped) {
387
- const ordered = members.slice().sort((left, right) => left.segmentedRow.componentIndex - right.segmentedRow.componentIndex);
388
- const expectedCount = ordered[0]?.segmentedRow?.componentCount ?? 0;
389
- const first = ordered[0]?.segmentedRow;
390
- if (!first) continue;
391
- const valid = expectedCount >= 2 && ordered.length === expectedCount && first?.boundaryBefore === "start" && ordered.every((row, index) => row.segmentedRow?.kind === "segmented-row-v1" && row.segmentedRow.groupId === groupId && row.segmentedRow.componentCount === expectedCount && row.segmentedRow.componentIndex === index && row.segmentedRow.repeatLabelOnComponents === first.repeatLabelOnComponents && (index === 0 ? row.segmentedRow.boundaryBefore === "start" : row.segmentedRow.boundaryBefore !== "start") && row.segmentedRow.displayLabel === first.displayLabel);
392
- if (!valid) continue;
393
- const totalSeats = ordered.reduce((sum, row) => sum + row.seatCount, 0);
394
- let adjacencyOffset = 0;
395
- let displayOffset = 0;
396
- for (const row of ordered) {
397
- if (row.segmentedRow.boundaryBefore === "break") adjacencyOffset += 1;
398
- segmented.set(row.id, {
399
- groupId,
400
- adjacencyOffset,
401
- displayOffset,
402
- displayLabel: first.displayLabel,
403
- totalSeats,
404
- canonical: ordered[0],
405
- viewFromSeatUrl: first.viewFromSeatUrl,
406
- viewFromSeatMeta: first.viewFromSeatMeta,
407
- confidenceEvidence: first.confidenceEvidence
408
- });
409
- adjacencyOffset += row.seatCount;
410
- displayOffset += row.seatCount;
411
- }
412
- }
413
- return segmented;
414
- }
415
-
416
- // src/core/labeling.ts
417
- var FULL_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
418
- var LOWER_ALPHABET = "abcdefghijklmnopqrstuvwxyz";
419
- function toBijectiveBase(index, alphabet) {
420
- const base = alphabet.length;
421
- let n = index + 1;
422
- let out = "";
423
- while (n > 0) {
424
- n -= 1;
425
- const rem = n % base;
426
- out = alphabet[rem] + out;
427
- n = Math.floor(n / base);
428
- }
429
- return out;
430
- }
431
- function toLetters(value, lower = false) {
432
- const alphabet = lower ? LOWER_ALPHABET : FULL_ALPHABET;
433
- return toBijectiveBase(Math.max(0, Math.floor(value) - 1), alphabet);
434
- }
435
- var ROMAN_TABLE = [
436
- [1e3, "M"],
437
- [900, "CM"],
438
- [500, "D"],
439
- [400, "CD"],
440
- [100, "C"],
441
- [90, "XC"],
442
- [50, "L"],
443
- [40, "XL"],
444
- [10, "X"],
445
- [9, "IX"],
446
- [5, "V"],
447
- [4, "IV"],
448
- [1, "I"]
449
- ];
450
- function toRoman(value) {
451
- if (!Number.isFinite(value) || value <= 0) return String(value);
452
- let remaining = Math.floor(value);
453
- let out = "";
454
- for (const [n, sym] of ROMAN_TABLE) {
455
- while (remaining >= n) {
456
- out += sym;
457
- remaining -= n;
458
- }
459
- }
460
- return out;
461
- }
462
-
463
- // src/core/seatNumbering.ts
464
- function centerRank(n) {
465
- const rank = new Array(n);
466
- Array.from({ length: n }, (_, i) => i).sort((a, b) => Math.abs(2 * a - (n - 1)) - Math.abs(2 * b - (n - 1)) || a - b).forEach((idx, k) => rank[idx] = k);
467
- return rank;
468
- }
469
- function seatLabelPart(row, i) {
470
- const rawStart = row.seatLabelStart ?? 1;
471
- const dir = row.seatNumbering?.direction ?? "ltr";
472
- const step = row.seatNumbering?.step ?? 1;
473
- const scheme = row.seatNumbering?.scheme ?? "decimal";
474
- const prefix = row.seatNumbering?.prefix ?? "";
475
- const endAt = row.seatNumbering?.endAt;
476
- const n = row.seatCount;
477
- if (scheme === "updown" || scheme === "updown-descending") {
478
- const half = Math.ceil(n / 2);
479
- const core2 = scheme === "updown" ? i < half ? rawStart + 2 * i : rawStart - 1 + 2 * (n - i) : i < half ? rawStart + 2 * (half - 1 - i) : rawStart + 1 + 2 * (i - half);
480
- return `${prefix}${core2}`;
481
- }
482
- const effStep = scheme === "odd" || scheme === "even" ? 2 : step;
483
- const start = endAt != null && Number.isFinite(endAt) ? endAt - (n - 1) * effStep : rawStart;
484
- const p = dir === "center" ? centerRank(n)[i] : dir === "rtl" ? n - 1 - i : i;
485
- let core;
486
- switch (scheme) {
487
- case "odd": {
488
- const firstOdd = start % 2 === 1 ? start : start + 1;
489
- core = String(firstOdd + p * 2);
490
- break;
491
- }
492
- case "even": {
493
- const firstEven = start % 2 === 0 ? start : start + 1;
494
- core = String(firstEven + p * 2);
495
- break;
496
- }
497
- case "roman":
498
- core = toRoman(start + p * step);
499
- break;
500
- case "letters-upper":
501
- core = toLetters(start + p * step, false);
502
- break;
503
- case "letters-lower":
504
- core = toLetters(start + p * step, true);
505
- break;
506
- case "decimal":
507
- default:
508
- core = String(start + p * step);
509
- break;
510
- }
511
- return `${prefix}${core}`;
512
- }
513
- function logicalNumberingRow(placement) {
514
- return {
515
- ...placement.canonical,
516
- seatCount: placement.totalSeats,
517
- label: placement.displayLabel,
518
- displayLabel: placement.displayLabel
519
- };
520
- }
521
- function seatInventoryLabel(row, physicalIndex, override) {
522
- return override?.label ?? `${row.label}-${seatLabelPart(row, physicalIndex)}`;
523
- }
524
- function seatDisplayLabel(row, physicalIndex, placement, override) {
525
- if (override?.displayLabel) return override.displayLabel;
526
- if (!placement) {
527
- const prefix = row.displayLabel ?? row.label;
528
- return `${prefix}-${seatLabelPart(row, physicalIndex)}`;
529
- }
530
- const numberingRow = logicalNumberingRow(placement);
531
- const ordinal = placement.displayOffset + physicalIndex;
532
- return `${placement.displayLabel}-${seatLabelPart(numberingRow, ordinal)}`;
533
- }
534
-
535
- // src/core/venueStructure.ts
536
- var BLOCK_LINK_RATIO = 1.8;
537
- function probesOf(pts) {
538
- const n = pts.length;
539
- if (n <= 3) return [...pts];
540
- return [pts[Math.floor(n * 0.25)], pts[Math.floor(n * 0.5)], pts[Math.floor(n * 0.75)]];
541
- }
542
- function distanceToPolyline(pts, x, y) {
543
- if (!pts.length) return Infinity;
544
- if (pts.length === 1) return Math.hypot(x - pts[0].x, y - pts[0].y);
545
- let best = Infinity;
546
- for (let i = 0; i + 1 < pts.length; i++) {
547
- const a = pts[i], b = pts[i + 1];
548
- const vx = b.x - a.x, vy = b.y - a.y;
549
- const len2 = vx * vx + vy * vy;
550
- let t = len2 > 1e-12 ? ((x - a.x) * vx + (y - a.y) * vy) / len2 : 0;
551
- if (t < 0) t = 0;
552
- else if (t > 1) t = 1;
553
- const d = Math.hypot(x - (a.x + t * vx), y - (a.y + t * vy));
554
- if (d < best) best = d;
555
- }
556
- return best;
557
- }
558
- function boundOf(pts) {
559
- let cx = 0, cy = 0;
560
- for (const p of pts) {
561
- cx += p.x;
562
- cy += p.y;
563
- }
564
- const n = pts.length || 1;
565
- cx /= n;
566
- cy /= n;
567
- let r = 0;
568
- for (const p of pts) {
569
- const d = Math.hypot(p.x - cx, p.y - cy);
570
- if (d > r) r = d;
571
- }
572
- return { cx, cy, r };
573
- }
574
- function boundGap(a, b) {
575
- return Math.hypot(a.cx - b.cx, a.cy - b.cy) - a.r - b.r;
576
- }
577
- function rowGap(a, b) {
578
- let best = Infinity;
579
- for (const p of probesOf(a)) {
580
- const d = distanceToPolyline(b, p.x, p.y);
581
- if (d < best) best = d;
582
- }
583
- for (const p of probesOf(b)) {
584
- const d = distanceToPolyline(a, p.x, p.y);
585
- if (d < best) best = d;
586
- }
587
- return best;
588
- }
589
- function orderAlongRow(pts, indices) {
590
- if (pts.length < 3) return { pts, seatIndices: indices };
591
- let cx = 0, cy = 0;
592
- for (const p of pts) {
593
- cx += p.x;
594
- cy += p.y;
595
- }
596
- cx /= pts.length;
597
- cy /= pts.length;
598
- let far = -1, ax = pts[0];
599
- for (const p of pts) {
600
- const d = Math.hypot(p.x - cx, p.y - cy);
601
- if (d > far) {
602
- far = d;
603
- ax = p;
604
- }
605
- }
606
- let dx = ax.x - cx, dy = ax.y - cy;
607
- const len = Math.hypot(dx, dy);
608
- if (len > 1e-9) {
609
- dx /= len;
610
- dy /= len;
611
- } else {
612
- dx = 1;
613
- dy = 0;
614
- }
615
- const order = pts.map((p, i) => ({ p, i, t: (p.x - cx) * dx + (p.y - cy) * dy })).sort((u, v) => u.t - v.t);
616
- return { pts: order.map((o) => o.p), seatIndices: order.map((o) => indices[o.i]) };
617
- }
618
- function fitCircle(pts) {
619
- const n = pts.length;
620
- if (n < 3) return null;
621
- let mx = 0, my = 0;
622
- for (const p of pts) {
623
- mx += p.x;
624
- my += p.y;
625
- }
626
- mx /= n;
627
- my /= n;
628
- let suu = 0, suv = 0, svv = 0, suuu = 0, svvv = 0, suvv = 0, svuu = 0;
629
- for (const p of pts) {
630
- const u = p.x - mx, v = p.y - my;
631
- suu += u * u;
632
- svv += v * v;
633
- suv += u * v;
634
- suuu += u * u * u;
635
- svvv += v * v * v;
636
- suvv += u * v * v;
637
- svuu += v * u * u;
638
- }
639
- const det = suu * svv - suv * suv;
640
- if (Math.abs(det) < 1e-9) return null;
641
- const b1 = (suuu + suvv) / 2;
642
- const b2 = (svvv + svuu) / 2;
643
- const uc = (b1 * svv - b2 * suv) / det;
644
- const vc = (b2 * suu - b1 * suv) / det;
645
- const cx = uc + mx, cy = vc + my;
646
- if (!Number.isFinite(cx) || !Number.isFinite(cy)) return null;
647
- return { cx, cy };
648
- }
649
- var CIRCLE_ROW_SPREAD_LIMIT = 0.15;
650
- function fitBlockAxis(group) {
651
- if (group.length < 2) return null;
652
- const cents = group.map((r) => {
653
- let x = 0, y = 0;
654
- for (const p of r.pts) {
655
- x += p.x;
656
- y += p.y;
657
- }
658
- return { x: x / r.pts.length, y: y / r.pts.length };
659
- });
660
- let ox = 0, oy = 0;
661
- for (const c of cents) {
662
- ox += c.x;
663
- oy += c.y;
664
- }
665
- ox /= cents.length;
666
- oy /= cents.length;
667
- let sxx = 0, sxy = 0, syy = 0;
668
- for (const c of cents) {
669
- const dx = c.x - ox, dy = c.y - oy;
670
- sxx += dx * dx;
671
- sxy += dx * dy;
672
- syy += dy * dy;
673
- }
674
- const tr = sxx + syy;
675
- const det = sxx * syy - sxy * sxy;
676
- const lambda = tr / 2 + Math.sqrt(Math.max(0, tr * tr / 4 - det));
677
- let ax, ay;
678
- if (Math.abs(sxy) > 1e-12) {
679
- ax = lambda - syy;
680
- ay = sxy;
681
- } else if (sxx >= syy) {
682
- ax = 1;
683
- ay = 0;
684
- } else {
685
- ax = 0;
686
- ay = 1;
687
- }
688
- const len = Math.hypot(ax, ay);
689
- if (!(len > 1e-12)) return null;
690
- ax /= len;
691
- ay /= len;
692
- let lo = Infinity, hi = -Infinity;
693
- const widths = [];
694
- for (const r of group) {
695
- let rlo = Infinity, rhi = -Infinity;
696
- for (const p of r.pts) {
697
- const t = p.x * ax + p.y * ay;
698
- if (t < rlo) rlo = t;
699
- if (t > rhi) rhi = t;
700
- if (t < lo) lo = t;
701
- if (t > hi) hi = t;
702
- }
703
- widths.push(rhi - rlo);
704
- }
705
- const range = hi - lo;
706
- if (!(range > 1e-9)) return null;
707
- widths.sort((a, b) => a - b);
708
- const p90 = widths[Math.min(widths.length - 1, Math.floor(widths.length * 0.9))];
709
- return p90 / range <= AXIS_ROW_WIDTH_LIMIT ? { x: ax, y: ay } : null;
710
- }
711
- var AXIS_ROW_WIDTH_LIMIT = 0.35;
712
- function resolveSection(sectionId, seats, seatIndices, focal) {
713
- const groups = /* @__PURE__ */ new Map();
714
- for (const i of seatIndices) {
715
- const s = seats[i];
716
- const key = s.rowId || `__seat-${i}`;
717
- let g = groups.get(key);
718
- if (!g) {
719
- g = { pts: [], idx: [] };
720
- groups.set(key, g);
721
- }
722
- g.pts.push({ x: s.x, y: s.y });
723
- g.idx.push(i);
724
- }
725
- if (!groups.size) return { sectionId, rows: [], blockCount: 0 };
726
- const rows = [];
727
- for (const [id, g] of groups) {
728
- const ordered = orderAlongRow(g.pts, g.idx);
729
- let sum = 0;
730
- for (const p of ordered.pts) sum += Math.hypot(p.x - focal.x, p.y - focal.y);
731
- rows.push({
732
- id,
733
- pts: ordered.pts,
734
- seatIndices: ordered.seatIndices,
735
- blockId: -1,
736
- ordinal: 0,
737
- blockDepth: 0,
738
- focalDistance: sum / ordered.pts.length
739
- });
740
- }
741
- const bounds = rows.map((r) => boundOf(r.pts));
742
- const nearest = [];
743
- for (let i = 0; i < rows.length; i++) {
744
- let best = Infinity;
745
- for (let j = 0; j < rows.length; j++) {
746
- if (i === j) continue;
747
- if (boundGap(bounds[i], bounds[j]) >= best) continue;
748
- const d = rowGap(rows[i].pts, rows[j].pts);
749
- if (d < best) best = d;
750
- }
751
- if (Number.isFinite(best)) nearest.push(best);
752
- }
753
- nearest.sort((a, b) => a - b);
754
- const typicalGap = nearest.length ? nearest[Math.floor(nearest.length / 2)] : 1;
755
- const linkDistance = Math.max(typicalGap * BLOCK_LINK_RATIO, 1e-6);
756
- const adjacency = rows.map(() => []);
757
- for (let i = 0; i < rows.length; i++) {
758
- for (let j = i + 1; j < rows.length; j++) {
759
- if (boundGap(bounds[i], bounds[j]) > linkDistance) continue;
760
- if (rowGap(rows[i].pts, rows[j].pts) <= linkDistance) {
761
- adjacency[i].push(j);
762
- adjacency[j].push(i);
763
- }
764
- }
765
- }
766
- let blockCount = 0;
767
- for (let i = 0; i < rows.length; i++) {
768
- if (rows[i].blockId !== -1) continue;
769
- const id = blockCount++;
770
- const stack = [i];
771
- rows[i].blockId = id;
772
- while (stack.length) {
773
- const k = stack.pop();
774
- for (const n of adjacency[k]) {
775
- if (rows[n].blockId !== -1) continue;
776
- rows[n].blockId = id;
777
- stack.push(n);
778
- }
779
- }
780
- }
781
- const byBlock = /* @__PURE__ */ new Map();
782
- for (const r of rows) {
783
- const a = byBlock.get(r.blockId) ?? [];
784
- a.push(r);
785
- byBlock.set(r.blockId, a);
786
- }
787
- const centres = [];
788
- for (const r of rows) {
789
- if (r.pts.length < 4) continue;
790
- const c = fitCircle(r.pts);
791
- if (!c) continue;
792
- if (!Number.isFinite(c.cx) || !Number.isFinite(c.cy)) continue;
793
- centres.push({ x: c.cx, y: c.cy });
794
- }
795
- const centre = centres.length >= 2 ? (() => {
796
- const xs = centres.map((c) => c.x).sort((a, b) => a - b);
797
- const ys = centres.map((c) => c.y).sort((a, b) => a - b);
798
- const mid = Math.floor(centres.length / 2);
799
- return { cx: xs[mid], cy: ys[mid] };
800
- })() : null;
801
- if (centre) {
802
- const radiusOf = (p) => Math.hypot(p.x - centre.cx, p.y - centre.cy);
803
- let lo = Infinity, hi = -Infinity;
804
- const spreads = [];
805
- for (const r of rows) {
806
- let rlo = Infinity, rhi = -Infinity;
807
- for (const p of r.pts) {
808
- const d = radiusOf(p);
809
- if (d < rlo) rlo = d;
810
- if (d > rhi) rhi = d;
811
- }
812
- spreads.push(rhi - rlo);
813
- if (rlo < lo) lo = rlo;
814
- if (rhi > hi) hi = rhi;
815
- }
816
- const range = hi - lo;
817
- spreads.sort((a, b) => a - b);
818
- const p90 = spreads[Math.min(spreads.length - 1, Math.floor(spreads.length * 0.9))];
819
- if (range > 1e-9 && p90 / range <= CIRCLE_ROW_SPREAD_LIMIT) {
820
- const withRadius = rows.map((r) => {
821
- let sum = 0;
822
- for (const p of r.pts) sum += radiusOf(p);
823
- return { row: r, radius: sum / r.pts.length };
824
- });
825
- let minR = Infinity;
826
- for (const w of withRadius) if (w.radius < minR) minR = w.radius;
827
- withRadius.sort((a, b) => a.radius - b.radius);
828
- let ordinal = -1, lastRadius = -Infinity;
829
- const tolerance = range / Math.max(1, withRadius.length) * 0.5;
830
- const ordered = [];
831
- for (const w of withRadius) {
832
- if (w.radius - lastRadius > tolerance) {
833
- ordinal++;
834
- lastRadius = w.radius;
835
- }
836
- w.row.ordinal = ordinal;
837
- w.row.blockDepth = w.radius - minR;
838
- ordered.push(w.row);
839
- }
840
- return { sectionId, rows: ordered, blockCount };
841
- }
842
- }
843
- const out = [];
844
- for (const [, group] of byBlock) {
845
- const axis = fitBlockAxis(group);
846
- if (axis) {
847
- const key = (r) => {
848
- let sum = 0;
849
- for (const p of r.pts) sum += p.x * axis.x + p.y * axis.y;
850
- return sum / r.pts.length;
851
- };
852
- group.sort((a, b) => key(a) - key(b));
853
- let depth = 0;
854
- for (let i = 0; i < group.length; i++) {
855
- if (i > 0) depth += rowGap(group[i - 1].pts, group[i].pts);
856
- group[i].ordinal = i;
857
- group[i].blockDepth = depth;
858
- out.push(group[i]);
859
- }
860
- } else {
861
- let front = Infinity;
862
- for (const r of group) if (r.focalDistance < front) front = r.focalDistance;
863
- group.sort((a, b) => a.focalDistance - b.focalDistance);
864
- for (let i = 0; i < group.length; i++) {
865
- group[i].ordinal = i;
866
- group[i].blockDepth = Math.max(0, group[i].focalDistance - front);
867
- out.push(group[i]);
868
- }
869
- }
870
- }
871
- return { sectionId, rows: out, blockCount };
872
- }
873
-
874
- // src/core/layout.ts
875
- function overrideAccessibility(o) {
876
- if (!o) return [];
877
- if (o.accessibility && o.accessibility.length) {
878
- return o.wheelchairSpaceType && !o.accessibility.includes("wheelchair") ? ["wheelchair", ...o.accessibility] : o.accessibility;
879
- }
880
- if (o.wheelchairSpaceType) return ["wheelchair"];
881
- return o.accessible ? ["wheelchair"] : [];
882
- }
883
- var DEG = Math.PI / 180;
884
- var SEAT_R = 9;
885
- var TABLE_SEAT_OFFSET = 16;
886
- function place(lx, ly, deg, origin) {
887
- const a = deg * DEG;
888
- const cos = Math.cos(a);
889
- const sin = Math.sin(a);
890
- return {
891
- x: origin.x + lx * cos - ly * sin,
892
- y: origin.y + lx * sin + ly * cos
893
- };
894
- }
895
- function rowSeatPositions(row) {
896
- const { seatCount, seatSpacing, curve, rotation, origin } = row;
897
- const out = [];
898
- if (row.path) return distributeAlongCubic(row.path, seatCount);
899
- if (seatCount <= 1) {
900
- if (seatCount === 1) out.push({ x: origin.x, y: origin.y });
901
- return out;
902
- }
903
- if (curve === 0) {
904
- for (let i = 0; i < seatCount; i++) out.push(place(i * seatSpacing, 0, rotation, origin));
905
- return out;
906
- }
907
- const arcStep = curve / (seatCount - 1) * DEG;
908
- const radius = seatSpacing / (2 * Math.sin(Math.abs(arcStep) / 2));
909
- for (let i = 0; i < seatCount; i++) {
910
- const phi = i * arcStep;
911
- const lx = radius * Math.sin(phi);
912
- const ly = -radius + radius * Math.cos(phi);
913
- out.push(place(lx, ly, rotation, origin));
914
- }
915
- return out;
916
- }
917
- function overrideMap(row) {
918
- const m = /* @__PURE__ */ new Map();
919
- if (row.overrides) for (const o of row.overrides) m.set(o.index, o);
920
- return m;
921
- }
922
- function rowInventoryCount(row) {
923
- const skipped = new Set((row.overrides ?? []).filter((override) => override.skip && Number.isInteger(override.index) && override.index >= 0 && override.index < row.seatCount).map((override) => override.index));
924
- return Math.max(0, row.seatCount - skipped.size);
925
- }
926
- function expandRowSlots(row, placement) {
927
- const ov = overrideMap(row);
928
- return rowSeatPositions(row).map((p, i) => {
929
- const o = ov.get(i);
930
- const accessibility = overrideAccessibility(o);
931
- const inventoryLabel = seatInventoryLabel(row, i, o);
932
- const commercial = { ...row.commercial, ...o?.commercial };
933
- return {
934
- index: i,
935
- x: p.x + (o?.dx ?? 0),
936
- y: p.y + (o?.dy ?? 0),
937
- label: inventoryLabel,
938
- displayLabel: seatDisplayLabel(row, i, placement, o),
939
- categoryKey: o?.categoryKey ?? row.categoryKey,
940
- skipped: !!o?.skip,
941
- accessible: accessibility.length > 0,
942
- accessibility,
943
- wheelchairSpaceType: o?.wheelchairSpaceType,
944
- commercial: Object.values(commercial).some((value) => value !== void 0 && value !== false && value !== "") ? commercial : void 0,
945
- viewUrl: o?.viewFromSeatUrl ?? row.viewFromSeatUrl,
946
- viewMeta: o?.viewFromSeatUrl ? o.viewFromSeatMeta : row.viewFromSeatMeta,
947
- labelStyle: o?.labelStyle
948
- };
949
- });
950
- }
951
- function expandRow(row) {
952
- const seats = [];
953
- for (const slot of expandRowSlots(row)) {
954
- if (slot.skipped) continue;
955
- seats.push({
956
- id: `${row.id}:${slot.index}`,
957
- label: slot.label,
958
- displayLabel: slot.displayLabel === slot.label ? void 0 : slot.displayLabel,
959
- x: slot.x,
960
- y: slot.y,
961
- rowId: row.id,
962
- categoryKey: slot.categoryKey,
963
- accessible: slot.accessible || void 0,
964
- accessibility: slot.accessibility.length ? slot.accessibility : void 0,
965
- wheelchairSpaceType: slot.wheelchairSpaceType,
966
- commercial: slot.commercial,
967
- viewUrl: slot.viewUrl,
968
- viewMeta: slot.viewMeta,
969
- labelStyle: slot.labelStyle
970
- });
971
- }
972
- return seats;
973
- }
974
- function tableSeatCountsBySide(t) {
975
- if (t.seatCountsBySide) return { ...t.seatCountsBySide };
976
- const enabled = t.sides && t.sides.length ? t.sides : ["top", "bottom"];
977
- const order = ["top", "bottom", "left", "right"].filter((side) => enabled.includes(side));
978
- const counts = { top: 0, bottom: 0, left: 0, right: 0 };
979
- if (!order.length) return counts;
980
- const n = Math.max(0, Math.round(t.seatCount));
981
- for (let index = 0; index < n; index++) counts[order[index % order.length]] += 1;
982
- return counts;
983
- }
984
- function expandTableSlots(t) {
985
- const seats = [];
986
- const n = Math.max(0, Math.round(t.seatCount));
987
- if (n === 0) return seats;
988
- const overrides = new Map((t.overrides ?? []).map((override) => [override.index, override]));
989
- const mk = (index, x, y, side) => {
990
- const override = overrides.get(index);
991
- const accessibility = overrideAccessibility(override);
992
- const label = override?.label ?? `${t.label}-${index + 1}`;
993
- const displayPrefix = t.displayLabel ?? t.label;
994
- return {
995
- index,
996
- label,
997
- displayLabel: override?.displayLabel ?? `${displayPrefix}-${index + 1}`,
998
- x: x + (override?.dx ?? 0),
999
- y: y + (override?.dy ?? 0),
1000
- categoryKey: override?.categoryKey ?? t.categoryKey,
1001
- skipped: !!override?.skip,
1002
- accessible: accessibility.length > 0,
1003
- accessibility,
1004
- wheelchairSpaceType: override?.wheelchairSpaceType,
1005
- commercial: override?.commercial,
1006
- viewUrl: override?.viewFromSeatUrl,
1007
- viewMeta: override?.viewFromSeatUrl ? override.viewFromSeatMeta : void 0,
1008
- labelStyle: override?.labelStyle,
1009
- ...side ? { side } : {}
1010
- };
1011
- };
1012
- if (t.shape === "round") {
1013
- const R = (t.radius ?? 40) + TABLE_SEAT_OFFSET;
1014
- const base = t.rotation * DEG;
1015
- const arc = Math.max(0, Math.min(360, t.seatArc ?? 360));
1016
- if (arc >= 360 || n === 1) {
1017
- for (let i = 0; i < n; i++) {
1018
- const a = base + i / n * 2 * Math.PI;
1019
- seats.push(mk(i, t.center.x + R * Math.cos(a), t.center.y + R * Math.sin(a)));
1020
- }
1021
- return seats;
1022
- }
1023
- const arcRad = arc * DEG;
1024
- const halfGap = (2 * Math.PI - arcRad) / 2;
1025
- const start = base + halfGap;
1026
- for (let i = 0; i < n; i++) {
1027
- const a = start + i / (n - 1) * arcRad;
1028
- seats.push(mk(i, t.center.x + R * Math.cos(a), t.center.y + R * Math.sin(a)));
1029
- }
1030
- return seats;
1031
- }
1032
- const w = t.width ?? 80;
1033
- const h = t.height ?? 50;
1034
- const counts = tableSeatCountsBySide(t);
1035
- const order = ["top", "bottom", "left", "right"];
1036
- let idx = 0;
1037
- for (const side of order) {
1038
- const count = counts[side];
1039
- for (let j = 0; j < count; j++) {
1040
- let localX;
1041
- let localY;
1042
- if (side === "top") {
1043
- localX = -w / 2 + (j + 0.5) * w / count;
1044
- localY = -h / 2 - TABLE_SEAT_OFFSET;
1045
- } else if (side === "bottom") {
1046
- localX = -w / 2 + (j + 0.5) * w / count;
1047
- localY = h / 2 + TABLE_SEAT_OFFSET;
1048
- } else if (side === "left") {
1049
- localX = -w / 2 - TABLE_SEAT_OFFSET;
1050
- localY = -h / 2 + (j + 0.5) * h / count;
1051
- } else {
1052
- localX = w / 2 + TABLE_SEAT_OFFSET;
1053
- localY = -h / 2 + (j + 0.5) * h / count;
1054
- }
1055
- const point = place(localX, localY, t.rotation, t.center);
1056
- seats.push(mk(idx++, point.x, point.y, side));
1057
- }
1058
- }
1059
- return seats;
1060
- }
1061
- function tableInventoryCount(t) {
1062
- if (t.bookAsWhole || t.variableOccupancy) return Math.max(0, Math.round(t.seatCount));
1063
- return expandTableSlots(t).filter((slot) => !slot.skipped).length;
1064
- }
1065
- function expandTable(t) {
1066
- return expandTableSlots(t).filter((slot) => !slot.skipped).map((slot) => ({
1067
- id: `${t.id}:${slot.index}`,
1068
- label: slot.label,
1069
- ...slot.displayLabel !== slot.label ? { displayLabel: slot.displayLabel } : {},
1070
- x: slot.x,
1071
- y: slot.y,
1072
- rowId: t.id,
1073
- categoryKey: slot.categoryKey,
1074
- ...slot.accessible ? { accessible: true } : {},
1075
- ...slot.accessibility.length ? { accessibility: slot.accessibility } : {},
1076
- ...slot.wheelchairSpaceType ? { wheelchairSpaceType: slot.wheelchairSpaceType } : {},
1077
- ...slot.commercial ? { commercial: slot.commercial } : {},
1078
- ...slot.viewUrl ? { viewUrl: slot.viewUrl } : {},
1079
- ...slot.viewUrl && slot.viewMeta ? { viewMeta: slot.viewMeta } : {},
1080
- ...slot.labelStyle ? { labelStyle: slot.labelStyle } : {}
1081
- }));
1082
- }
1083
- function expandBooth(b) {
1084
- return [
1085
- {
1086
- id: `${b.id}:0`,
1087
- label: b.label,
1088
- ...b.displayLabel && b.displayLabel !== b.label ? { displayLabel: b.displayLabel } : {},
1089
- x: b.center.x,
1090
- y: b.center.y,
1091
- rowId: b.id,
1092
- categoryKey: b.categoryKey,
1093
- kind: "booth"
1094
- }
1095
- ];
1096
- }
1097
- function pointInPolygon(p, poly) {
1098
- let inside = false;
1099
- for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {
1100
- const xi = poly[i].x;
1101
- const yi = poly[i].y;
1102
- const xj = poly[j].x;
1103
- const yj = poly[j].y;
1104
- const hit = yi > p.y !== yj > p.y && p.x < (xj - xi) * (p.y - yi) / (yj - yi) + xi;
1105
- if (hit) inside = !inside;
1106
- }
1107
- return inside;
1108
- }
1109
- function pointOnPolygonBoundary(p, poly) {
1110
- return poly.some((start, index) => {
1111
- const end = poly[(index + 1) % poly.length];
1112
- const cross = (p.y - start.y) * (end.x - start.x) - (p.x - start.x) * (end.y - start.y);
1113
- if (Math.abs(cross) > 1e-7) return false;
1114
- const dot = (p.x - start.x) * (end.x - start.x) + (p.y - start.y) * (end.y - start.y);
1115
- const lengthSquared = (end.x - start.x) ** 2 + (end.y - start.y) ** 2;
1116
- return dot >= -1e-7 && dot <= lengthSquared + 1e-7;
1117
- });
1118
- }
1119
- function pointInPolygonWithHoles(p, outer, holes) {
1120
- return pointInPolygon(p, outer) && !(holes ?? []).some((hole) => pointInPolygon(p, hole) || pointOnPolygonBoundary(p, hole));
1121
- }
1122
- function polygonLabelPoint(outer, holes) {
1123
- return polygonInscribedAnchor(outer, holes).point;
1124
- }
1125
- function polygonCentroid(pts) {
1126
- if (!pts.length) return { x: 0, y: 0 };
1127
- let x = 0;
1128
- let y = 0;
1129
- for (const p of pts) {
1130
- x += p.x;
1131
- y += p.y;
1132
- }
1133
- return { x: x / pts.length, y: y / pts.length };
1134
- }
1135
- function objectCenter(o) {
1136
- switch (o.type) {
1137
- case "row": {
1138
- const seats = expandRow(o);
1139
- if (!seats.length) return { x: o.origin.x, y: o.origin.y };
1140
- let x = 0;
1141
- let y = 0;
1142
- for (const s of seats) {
1143
- x += s.x;
1144
- y += s.y;
1145
- }
1146
- return { x: x / seats.length, y: y / seats.length };
1147
- }
1148
- case "table":
1149
- case "booth":
1150
- return { x: o.center.x, y: o.center.y };
1151
- case "gaArea":
1152
- return polygonCentroid(o.points);
1153
- case "section":
1154
- return polygonCentroid(o.outline);
1155
- case "text":
1156
- return { x: o.position.x, y: o.position.y };
1157
- case "shape":
1158
- if (o.points && o.points.length) return polygonCentroid(o.points);
1159
- if (o.x != null && o.y != null && o.width != null && o.height != null) {
1160
- return { x: o.x + o.width / 2, y: o.y + o.height / 2 };
1161
- }
1162
- return { x: o.x ?? 0, y: o.y ?? 0 };
1163
- case "decorImage":
1164
- return { x: o.x + o.width / 2, y: o.y + o.height / 2 };
1165
- }
1166
- }
1167
- function samePoints(left, right) {
1168
- return left.length === right.length && left.every((point, index) => point.x === right[index].x && point.y === right[index].y);
1169
- }
1170
- function sameGASurfaceAsSection(object, section) {
1171
- if (object.type !== "gaArea" || !samePoints(object.points, section.outline)) return false;
1172
- const objectHoles = object.holes ?? [];
1173
- const sectionHoles = section.holes ?? [];
1174
- return objectHoles.length === sectionHoles.length && objectHoles.every((hole, index) => samePoints(hole, sectionHoles[index]));
1175
- }
1176
- function owningSectionForObject(objects, object) {
1177
- const sections = objects.filter((candidate) => candidate.type === "section");
1178
- const referencedLogicalId = "referenceInventorySource" in object ? object.referenceInventorySource?.logicalSectionId : void 0;
1179
- const center = objectCenter(object);
1180
- const referencedOwner = referencedLogicalId ? sections.find((section) => (section.logicalSectionId ?? section.id) === referencedLogicalId && (sameGASurfaceAsSection(object, section) || pointInPolygonWithHoles(center, section.outline, section.holes))) : void 0;
1181
- return referencedOwner ?? sections.find((section) => pointInPolygonWithHoles(center, section.outline, section.holes));
1182
- }
1183
- function floorsOf(doc) {
1184
- if (doc.floors && doc.floors.length) return doc.floors;
1185
- return [{
1186
- id: "floor-0",
1187
- name: "Main",
1188
- objects: doc.objects,
1189
- focalPoint: doc.focalPoint,
1190
- referenceImage: doc.referenceImage,
1191
- backgroundImage: doc.backgroundImage
1192
- }];
1193
- }
1194
- function floorObjects(doc, floorId) {
1195
- const floors = floorsOf(doc);
1196
- return (floorId ? floors.find((f) => f.id === floorId) : floors[0])?.objects ?? [];
1197
- }
1198
- function allObjects(doc) {
1199
- return doc.floors && doc.floors.length ? doc.floors.flatMap((f) => f.objects) : doc.objects;
1200
- }
1201
- function translateObject(o, dx, dy) {
1202
- const p = (pt) => ({ x: pt.x + dx, y: pt.y + dy });
1203
- const pts = (a) => a.map(p);
1204
- switch (o.type) {
1205
- case "row":
1206
- return { ...o, origin: p(o.origin) };
1207
- case "table":
1208
- case "booth":
1209
- return { ...o, center: p(o.center) };
1210
- case "gaArea":
1211
- return { ...o, points: pts(o.points), ...o.holes ? { holes: o.holes.map(pts) } : {} };
1212
- case "section":
1213
- return {
1214
- ...o,
1215
- outline: pts(o.outline),
1216
- ...o.outlinePath ? { outlinePath: translateSectionOutlinePath(o.outlinePath, dx, dy) } : {},
1217
- ...o.holes ? { holes: o.holes.map(pts) } : {}
1218
- };
1219
- case "text":
1220
- return { ...o, position: p(o.position) };
1221
- case "shape":
1222
- return {
1223
- ...o,
1224
- ...o.points ? { points: pts(o.points) } : {},
1225
- ...o.x != null ? { x: o.x + dx } : {},
1226
- ...o.y != null ? { y: o.y + dy } : {}
1227
- };
1228
- case "decorImage":
1229
- return { ...o, x: o.x + dx, y: o.y + dy };
1230
- }
1231
- }
1232
- function stackFloors(doc, spread = 900) {
1233
- if (!doc.floors || doc.floors.length < 2) return doc;
1234
- const objects = [];
1235
- doc.floors.forEach((f, i) => {
1236
- const dy = -i * spread;
1237
- for (const o of f.objects) objects.push(dy === 0 ? o : translateObject(o, 0, dy));
1238
- });
1239
- return { ...doc, objects, floors: void 0 };
1240
- }
1241
- function layoutFloorOverview(doc) {
1242
- const floors = doc.floors;
1243
- if (!floors || floors.length < 2) return doc;
1244
- const translations = floorOverviewTranslations(doc);
1245
- const objects = [];
1246
- floors.forEach((floor, index) => {
1247
- const { x: dx, y: dy } = translations[index];
1248
- for (const object of floor.objects) objects.push(translateObject(object, dx, dy));
1249
- });
1250
- return {
1251
- ...doc,
1252
- objects,
1253
- floors: void 0,
1254
- referenceImage: void 0,
1255
- backgroundImage: void 0
1256
- };
1257
- }
1258
- function floorOverviewTranslations(doc) {
1259
- const floors = doc.floors;
1260
- if (!floors?.length) return [{ x: 0, y: 0 }];
1261
- if (floors.length < 2) return floors.map(() => ({ x: 0, y: 0 }));
1262
- const bounds = floors.map((floor) => chartBounds({
1263
- ...doc,
1264
- objects: floor.objects,
1265
- floors: void 0,
1266
- focalPoint: floor.focalPoint,
1267
- referenceImage: void 0,
1268
- backgroundImage: void 0
1269
- }));
1270
- const characteristic = Math.max(1, ...bounds.map((bound) => Math.max(bound.width, bound.height)));
1271
- const gap = Math.max(64, Math.min(240, characteristic * 0.08));
1272
- const targetAspect = 16 / 10;
1273
- let best = null;
1274
- for (let columns2 = 1; columns2 <= floors.length; columns2 += 1) {
1275
- const rows = Math.ceil(floors.length / columns2);
1276
- const columnWidths2 = new Array(columns2).fill(0);
1277
- const rowHeights2 = new Array(rows).fill(0);
1278
- bounds.forEach((bound, index) => {
1279
- const column = index % columns2;
1280
- const row = Math.floor(index / columns2);
1281
- columnWidths2[column] = Math.max(columnWidths2[column], bound.width);
1282
- rowHeights2[row] = Math.max(rowHeights2[row], bound.height);
1283
- });
1284
- const width = columnWidths2.reduce((sum, value) => sum + value, 0) + gap * (columns2 - 1);
1285
- const height = rowHeights2.reduce((sum, value) => sum + value, 0) + gap * (rows - 1);
1286
- const unusedCells = columns2 * rows - floors.length;
1287
- const score = Math.abs(Math.log(width / Math.max(1, height) / targetAspect)) + unusedCells * 0.04;
1288
- if (!best || score < best.score) best = { columns: columns2, columnWidths: columnWidths2, rowHeights: rowHeights2, score };
1289
- }
1290
- const { columns, columnWidths, rowHeights } = best;
1291
- const columnOffsets = [];
1292
- const rowOffsets = [];
1293
- columnWidths.reduce((offset, width, index) => {
1294
- columnOffsets[index] = offset;
1295
- return offset + width + gap;
1296
- }, 0);
1297
- rowHeights.reduce((offset, height, index) => {
1298
- rowOffsets[index] = offset;
1299
- return offset + height + gap;
1300
- }, 0);
1301
- return floors.map((_floor, index) => {
1302
- const bound = bounds[index];
1303
- const column = index % columns;
1304
- const row = Math.floor(index / columns);
1305
- const targetX = columnOffsets[column] + (columnWidths[column] - bound.width) / 2;
1306
- const targetY = rowOffsets[row] + (rowHeights[row] - bound.height) / 2;
1307
- return { x: targetX - bound.x, y: targetY - bound.y };
1308
- });
1309
- }
1310
- function expandFloorObjects(objects, zones, fallbackFocal, activeConfigurationId, viewFallback, confidenceFallback) {
1311
- const out = [];
1312
- const segmented = resolveSegmentedRowGroups(objects);
1313
- const appliesToConfiguration = (meta) => !meta?.eventConfigurationId || meta.eventConfigurationId === activeConfigurationId;
1314
- const confidenceApplies = (evidence) => !!evidence && (!evidence.eventConfigurationId || evidence.eventConfigurationId === activeConfigurationId);
1315
- const resolvedConfidence = (evidence, coverage) => confidenceApplies(evidence) ? { ...evidence, coverage } : void 0;
1316
- for (const obj of objects) {
1317
- let seats = [];
1318
- if (obj.type === "row") seats = expandRow(obj);
1319
- else if (obj.type === "table") seats = expandTable(obj);
1320
- else if (obj.type === "booth") seats = expandBooth(obj);
1321
- if (!seats.length) continue;
1322
- for (const seat of seats) {
1323
- if (seat.viewUrl && !appliesToConfiguration(seat.viewMeta)) {
1324
- seat.viewUrl = void 0;
1325
- seat.viewMeta = void 0;
1326
- }
1327
- }
1328
- if (obj.type === "row") {
1329
- const logical = segmented.get(obj.id);
1330
- if (logical) {
1331
- const overrides = new Map((obj.overrides ?? []).map((override) => [override.index, override]));
1332
- for (const seat of seats) {
1333
- const physicalIndex = Number(seat.id.slice(seat.id.lastIndexOf(":") + 1));
1334
- if (!Number.isInteger(physicalIndex)) continue;
1335
- seat.logicalRowId = logical.groupId;
1336
- seat.logicalSeatIndex = logical.adjacencyOffset + physicalIndex;
1337
- if (!overrides.get(physicalIndex)?.displayLabel) {
1338
- seat.displayLabel = seatDisplayLabel(obj, physicalIndex, logical);
1339
- }
1340
- if (!seat.viewUrl && logical.viewFromSeatUrl && appliesToConfiguration(logical.viewFromSeatMeta)) {
1341
- seat.viewUrl = logical.viewFromSeatUrl;
1342
- seat.viewMeta = logical.viewFromSeatMeta;
1343
- }
1344
- const exactEvidence = overrides.get(physicalIndex)?.confidenceEvidence;
1345
- seat.confidenceEvidence = resolvedConfidence(exactEvidence, "exact-seat") ?? resolvedConfidence(obj.confidenceEvidence, "row-representative") ?? resolvedConfidence(logical.confidenceEvidence, "row-representative");
1346
- }
1347
- }
1348
- }
1349
- const owner = owningSectionForObject(objects, obj);
1350
- const inheritedView = owner?.viewFromSeatUrl;
1351
- const zone = owner?.zone ? zones?.find((candidate) => candidate.id === owner.zone) : void 0;
1352
- const resolvedFocal = zone?.focalPoint ?? fallbackFocal;
1353
- for (const seat of seats) {
1354
- if (!seat.confidenceEvidence) {
1355
- const physicalIndex = Number(seat.id.slice(seat.id.lastIndexOf(":") + 1));
1356
- const exactEvidence = (obj.type === "row" || obj.type === "table") && Number.isInteger(physicalIndex) ? obj.overrides?.find((override) => override.index === physicalIndex)?.confidenceEvidence : void 0;
1357
- seat.confidenceEvidence = resolvedConfidence(exactEvidence, "exact-seat") ?? (obj.type === "row" ? resolvedConfidence(obj.confidenceEvidence, "row-representative") : void 0);
1358
- }
1359
- seat.confidenceEvidence ??= resolvedConfidence(owner?.confidenceEvidence, "section-representative") ?? (confidenceFallback ? resolvedConfidence(confidenceFallback.evidence, confidenceFallback.coverage) : void 0);
1360
- if (!seat.viewUrl && inheritedView && appliesToConfiguration(owner?.viewFromSeatMeta)) {
1361
- seat.viewUrl = inheritedView;
1362
- seat.viewMeta = owner?.viewFromSeatMeta;
1363
- }
1364
- if (!seat.viewUrl && viewFallback && appliesToConfiguration(viewFallback.meta)) {
1365
- seat.viewUrl = viewFallback.url;
1366
- seat.viewMeta = viewFallback.meta;
1367
- }
1368
- if (owner) seat.sectionId = owner.logicalSectionId ?? owner.id;
1369
- if (owner?.zone) seat.zoneId = owner.zone;
1370
- if (resolvedFocal) seat.focalPoint = { ...resolvedFocal };
1371
- }
1372
- out.push(...seats);
1373
- }
1374
- return out;
1375
- }
1376
- function expandChart(doc, options = {}) {
1377
- if (doc.floors?.length) {
1378
- const out2 = [];
1379
- for (const floor of doc.floors) {
1380
- const floorFocal = floor.focalPoint ?? doc.focalPoint;
1381
- const floorView = floor.viewFromSeatUrl ? { url: floor.viewFromSeatUrl, meta: floor.viewFromSeatMeta } : doc.viewFromSeatUrl ? { url: doc.viewFromSeatUrl, meta: doc.viewFromSeatMeta } : void 0;
1382
- const confidenceFallback = floor.confidenceEvidence ? { evidence: floor.confidenceEvidence, coverage: "floor-representative" } : doc.confidenceEvidence ? { evidence: doc.confidenceEvidence, coverage: "venue-representative" } : void 0;
1383
- const seats = expandFloorObjects(
1384
- floor.objects,
1385
- doc.zones,
1386
- floorFocal,
1387
- doc.eventConfigurationId,
1388
- floorView,
1389
- confidenceFallback
1390
- );
1391
- if (options.resolveEyeHeights !== false) {
1392
- assignEyeHeights(floor.objects, floor.focalPoint ?? doc.focalPoint, floor.baseHeightM ?? 0, seats);
1393
- }
1394
- out2.push(...seats);
1395
- }
1396
- return out2;
1397
- }
1398
- const out = expandFloorObjects(
1399
- doc.objects,
1400
- doc.zones,
1401
- doc.focalPoint,
1402
- doc.eventConfigurationId,
1403
- doc.viewFromSeatUrl ? { url: doc.viewFromSeatUrl, meta: doc.viewFromSeatMeta } : void 0,
1404
- doc.confidenceEvidence ? { evidence: doc.confidenceEvidence, coverage: "venue-representative" } : void 0
1405
- );
1406
- if (options.resolveEyeHeights !== false) {
1407
- assignEyeHeights(doc.objects, doc.focalPoint, options.floorBaseHeightM ?? 0, out);
1408
- }
1409
- return out;
1410
- }
1411
- function assignEyeHeights(objects, focal, floorBaseHeightM, seats) {
1412
- const sections = objects.filter((o) => o.type === "section");
1413
- const hasGeometry = floorBaseHeightM > 0 || sections.some((s) => s.height !== void 0 || s.rake !== void 0 || (s.elevation ?? 0) > 0);
1414
- if (!sections.length || !hasGeometry || !focal) {
1415
- for (const seat of seats) seat.eyeHeightM = floorBaseHeightM + SEATED_EYE_HEIGHT_M;
1416
- return;
1417
- }
1418
- const owner = new Array(seats.length);
1419
- const geo = /* @__PURE__ */ new Map();
1420
- const seatsBySection = /* @__PURE__ */ new Map();
1421
- for (let i = 0; i < seats.length; i++) {
1422
- const seat = seats[i];
1423
- const sec = sections.find((s) => pointInPolygonWithHoles({ x: seat.x, y: seat.y }, s.outline, s.holes)) ?? null;
1424
- owner[i] = sec;
1425
- if (!sec) continue;
1426
- if (!geo.has(sec.id)) geo.set(sec.id, sectionGeometry(sec, { floorBaseHeightM }));
1427
- const list = seatsBySection.get(sec.id);
1428
- if (list) list.push(i);
1429
- else seatsBySection.set(sec.id, [i]);
1430
- }
1431
- const seatLevel = new Array(seats.length).fill(void 0);
1432
- for (const [secId, indices] of seatsBySection) {
1433
- const g = geo.get(secId);
1434
- if (!g) continue;
1435
- const rakeTan = g.rake > 0 ? Math.tan(g.rake * Math.PI / 180) : 0;
1436
- const structure = resolveSection(secId, seats, indices, focal);
1437
- for (const row of structure.rows) {
1438
- const riseM = row.blockDepth * METRES_PER_CHART_UNIT * rakeTan;
1439
- const level = g.height + riseM;
1440
- for (const si of row.seatIndices) seatLevel[si] = level;
1441
- }
1442
- }
1443
- for (let i = 0; i < seats.length; i++) {
1444
- const seat = seats[i];
1445
- const sec = owner[i];
1446
- if (!sec) {
1447
- seat.eyeHeightM = floorBaseHeightM + SEATED_EYE_HEIGHT_M;
1448
- continue;
1449
- }
1450
- const g = geo.get(sec.id);
1451
- seat.eyeHeightM = (seatLevel[i] ?? g.height) + SEATED_EYE_HEIGHT_M;
1452
- }
1453
- }
1454
- var PAD = 40;
1455
- function chartBounds(doc) {
1456
- let minX = Infinity;
1457
- let minY = Infinity;
1458
- let maxX = -Infinity;
1459
- let maxY = -Infinity;
1460
- const acc = (x, y) => {
1461
- if (x < minX) minX = x;
1462
- if (y < minY) minY = y;
1463
- if (x > maxX) maxX = x;
1464
- if (y > maxY) maxY = y;
1465
- };
1466
- for (const obj of allObjects(doc)) {
1467
- if (obj.type === "row") {
1468
- const overrides = new Map((obj.overrides ?? []).map((override) => [override.index, override]));
1469
- rowSeatPositions(obj).forEach((point, index) => {
1470
- const override = overrides.get(index);
1471
- if (override?.skip) return;
1472
- acc(point.x + (override?.dx ?? 0), point.y + (override?.dy ?? 0));
1473
- });
1474
- } else if (obj.type === "gaArea") {
1475
- for (const p of obj.points) acc(p.x, p.y);
1476
- } else if (obj.type === "section") {
1477
- for (const p of obj.outline) acc(p.x, p.y);
1478
- } else if (obj.type === "decorImage") {
1479
- acc(obj.x, obj.y);
1480
- acc(obj.x + obj.width, obj.y + obj.height);
1481
- } else if (obj.type === "shape") {
1482
- if (obj.points && obj.points.length) {
1483
- for (const p of obj.points) acc(p.x, p.y);
1484
- } else if (obj.x != null && obj.y != null && obj.width != null && obj.height != null) {
1485
- acc(obj.x, obj.y);
1486
- acc(obj.x + obj.width, obj.y + obj.height);
1487
- }
1488
- } else if (obj.type === "table") {
1489
- const off = TABLE_SEAT_OFFSET + SEAT_R;
1490
- const ext = obj.shape === "round" ? (obj.radius ?? 40) + off : Math.max((obj.width ?? 80) / 2, (obj.height ?? 50) / 2) + off;
1491
- acc(obj.center.x - ext, obj.center.y - ext);
1492
- acc(obj.center.x + ext, obj.center.y + ext);
1493
- } else if (obj.type === "booth") {
1494
- const ext = Math.max(obj.width, obj.height) / 2;
1495
- acc(obj.center.x - ext, obj.center.y - ext);
1496
- acc(obj.center.x + ext, obj.center.y + ext);
1497
- } else if (obj.type === "text") {
1498
- const box = textLayoutMetrics(obj);
1499
- acc(obj.position.x, obj.position.y);
1500
- acc(obj.position.x + box.width, obj.position.y + box.height);
1501
- }
1502
- }
1503
- for (const image of [doc.referenceImage, doc.backgroundImage]) {
1504
- if (!image) continue;
1505
- const { center, width } = image;
1506
- const bh = width * 3 / 4;
1507
- acc(center.x - width / 2, center.y - bh / 2);
1508
- acc(center.x + width / 2, center.y + bh / 2);
1509
- }
1510
- if (!isFinite(minX)) {
1511
- const f = doc.focalPoint ?? { x: 0, y: 0 };
1512
- return { x: f.x - 200, y: f.y - 200, width: 400, height: 400 };
1513
- }
1514
- return {
1515
- x: minX - PAD,
1516
- y: minY - PAD,
1517
- width: maxX - minX + PAD * 2,
1518
- height: maxY - minY + PAD * 2
1519
- };
1520
- }
1521
-
1522
- export {
1523
- ACCESSIBILITY_TYPES,
1524
- accessibilityMeta,
1525
- ACCESSIBILITY_RING_COLOR,
1526
- accessibilityRingColor,
1527
- SEAT_COMMERCIAL_MARKS,
1528
- seatCommercialMeta,
1529
- LABEL_STYLE_MIN_SIZE,
1530
- LABEL_STYLE_MAX_SIZE,
1531
- SURROUNDINGS_SHAPE_ROLES,
1532
- layerOf,
1533
- CHART_STORAGE_KEY,
1534
- distanceToRings,
1535
- polygonNetArea,
1536
- METRES_PER_CHART_UNIT,
1537
- CHART_UNITS_PER_METRE,
1538
- TIER_HEIGHT_M,
1539
- SEATED_EYE_HEIGHT_M,
1540
- sectionElevationTier,
1541
- sectionGeometry,
1542
- distanceToPolyline,
1543
- fitCircle,
1544
- resolveSection,
1545
- rowSeatPositions,
1546
- rowInventoryCount,
1547
- expandRowSlots,
1548
- expandRow,
1549
- tableSeatCountsBySide,
1550
- expandTableSlots,
1551
- tableInventoryCount,
1552
- expandTable,
1553
- expandBooth,
1554
- pointInPolygon,
1555
- pointInPolygonWithHoles,
1556
- polygonLabelPoint,
1557
- objectCenter,
1558
- owningSectionForObject,
1559
- floorsOf,
1560
- floorObjects,
1561
- allObjects,
1562
- translateObject,
1563
- stackFloors,
1564
- layoutFloorOverview,
1565
- floorOverviewTranslations,
1566
- expandChart,
1567
- chartBounds
1568
- };
1569
- //# sourceMappingURL=chunk-UID7KN44.js.map