@spatial-engine/core 0.0.1

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.
@@ -0,0 +1,295 @@
1
+ export { LidarDoneMessage, LidarInitMessage, LidarReadyMessage, LidarSweepMessage, LidarWorkerInMessage, LidarWorkerOutMessage, createLidarProcessor } from './lidar-worker.js';
2
+
3
+ /**
4
+ * AABB (Axis-Aligned Bounding Box) stored as a flat Float32Array slice.
5
+ * Layout: [minX, minY, minZ, maxX, maxY, maxZ]
6
+ */
7
+ declare const AABB_STRIDE = 6;
8
+ /**
9
+ * A pool-backed, zero-GC AABB store.
10
+ * Each AABB occupies AABB_STRIDE floats in the underlying buffer.
11
+ *
12
+ * When a `SharedArrayBuffer` is provided, the pool's data is accessible from
13
+ * multiple threads (e.g. a Web Worker) with no copying.
14
+ */
15
+ declare class AABBPool {
16
+ private readonly buffer;
17
+ private count;
18
+ constructor(capacity: number, sharedBuffer?: SharedArrayBuffer);
19
+ /**
20
+ * Create an AABBPool backed by a new `SharedArrayBuffer`.
21
+ * Both the pool and the underlying `SharedArrayBuffer` are returned so the
22
+ * caller can transfer the buffer to a `Worker` via `postMessage`.
23
+ */
24
+ static createShared(capacity: number): {
25
+ pool: AABBPool;
26
+ sab: SharedArrayBuffer;
27
+ };
28
+ /** Allocate a new AABB slot and return its index. */
29
+ allocate(): number;
30
+ /** Set the bounds of an AABB at the given index. */
31
+ set(index: number, minX: number, minY: number, minZ: number, maxX: number, maxY: number, maxZ: number): void;
32
+ /** Read a single component value from the buffer. */
33
+ get(index: number, component: number): number;
34
+ /** Returns the number of allocated AABBs. */
35
+ get size(): number;
36
+ /** Reset the pool (all allocations freed, no GC). */
37
+ reset(): void;
38
+ }
39
+ /**
40
+ * Expand AABB `a` in-place so it also fully contains AABB `b`.
41
+ */
42
+ declare function aabbExpand(pool: AABBPool, a: number, b: number): void;
43
+ /**
44
+ * Merge AABBs `a` and `b` into `dest` (a pre-allocated slot), storing their union.
45
+ */
46
+ declare function aabbMerge(pool: AABBPool, dest: number, a: number, b: number): void;
47
+ /**
48
+ * Test whether two AABBs (by index in the same pool) intersect.
49
+ */
50
+ declare function aabbIntersects(pool: AABBPool, a: number, b: number): boolean;
51
+
52
+ /**
53
+ * Ray stored as origin + direction (unit vector).
54
+ * Layout: [ox, oy, oz, dx, dy, dz]
55
+ */
56
+ declare const RAY_STRIDE = 6;
57
+ /** A pool-backed, zero-GC Ray store.
58
+ *
59
+ * When a `SharedArrayBuffer` is provided, the pool's data is accessible from
60
+ * multiple threads (e.g. a Web Worker) with no copying.
61
+ */
62
+ declare class RayPool {
63
+ private readonly buffer;
64
+ private count;
65
+ constructor(capacity: number, sharedBuffer?: SharedArrayBuffer);
66
+ /**
67
+ * Create a RayPool backed by a new `SharedArrayBuffer`.
68
+ * Both the pool and the underlying `SharedArrayBuffer` are returned so the
69
+ * caller can transfer the buffer to a `Worker` via `postMessage`.
70
+ */
71
+ static createShared(capacity: number): {
72
+ pool: RayPool;
73
+ sab: SharedArrayBuffer;
74
+ };
75
+ /** Allocate a new Ray slot and return its index. */
76
+ allocate(): number;
77
+ /** Set origin and direction of a ray at the given index. */
78
+ set(index: number, ox: number, oy: number, oz: number, dx: number, dy: number, dz: number): void;
79
+ /** Read a single component value from the buffer. */
80
+ get(index: number, component: number): number;
81
+ /** Returns the number of allocated Rays. */
82
+ get size(): number;
83
+ /** Reset the pool (all allocations freed, no GC). */
84
+ reset(): void;
85
+ }
86
+ /**
87
+ * Optimized branchless slab-method ray–AABB intersection test.
88
+ *
89
+ * Operates purely on flat Float32Arrays with no per-axis direction branches.
90
+ * When a direction component is zero, IEEE 754 produces ±Infinity for the
91
+ * reciprocal, which propagates correctly through the min/max slab computation:
92
+ * - origin inside the slab → [−∞, +∞] interval (no constraint)
93
+ * - origin outside the slab → either [+∞, +∞] or [−∞, −∞] → forces a miss
94
+ *
95
+ * Returns the parametric hit distance `t` (>= 0) if the ray intersects the
96
+ * AABB, or -1 if there is no intersection (miss or box entirely behind origin).
97
+ */
98
+ declare function rayIntersectsAABB(rayBuf: Float32Array, rayOffset: number, aabbBuf: Float32Array, aabbOffset: number): number;
99
+
100
+ /**
101
+ * A generic Object Pool that manages a fixed set of integer indices.
102
+ *
103
+ * Pre-allocates a free-list on construction so that acquire() and release()
104
+ * operate without any heap allocation.
105
+ */
106
+ declare class ObjectPool {
107
+ private readonly freeList;
108
+ private top;
109
+ /** Total number of slots in the pool. */
110
+ readonly capacity: number;
111
+ constructor(capacity: number);
112
+ /** Number of indices currently available for acquisition. */
113
+ get available(): number;
114
+ /**
115
+ * Acquire a free index from the pool.
116
+ * Returns the index, or `null` when the pool is exhausted.
117
+ */
118
+ acquire(): number | null;
119
+ /**
120
+ * Release a previously acquired index back to the pool.
121
+ * Throws if the index is out of range or the pool is already full.
122
+ */
123
+ release(index: number): void;
124
+ }
125
+
126
+ /**
127
+ * Flat Array Math Utilities
128
+ *
129
+ * Zero-allocation Vec3 math that reads directly from a Float32Array
130
+ * given a start index, without creating any Vector3 objects.
131
+ *
132
+ * All index parameters (`i`, `j`, `outOffset`) are raw flat-array offsets.
133
+ */
134
+ /**
135
+ * Compute the dot product of two Vec3s stored in `buf` at offsets `i` and `j`.
136
+ */
137
+ declare function vec3Dot(buf: Float32Array, i: number, j: number): number;
138
+ /**
139
+ * Compute the squared distance between two Vec3s stored in `buf` at offsets `i` and `j`.
140
+ */
141
+ declare function vec3DistanceSq(buf: Float32Array, i: number, j: number): number;
142
+ /**
143
+ * Compute the Euclidean distance between two Vec3s stored in `buf` at offsets `i` and `j`.
144
+ */
145
+ declare function vec3Distance(buf: Float32Array, i: number, j: number): number;
146
+ /**
147
+ * Compute the cross product of two Vec3s in `buf` at offsets `i` and `j`,
148
+ * and write the result into `out` starting at `outOffset`.
149
+ */
150
+ declare function vec3Cross(out: Float32Array, outOffset: number, buf: Float32Array, i: number, j: number): void;
151
+
152
+ /**
153
+ * Octree node stored as a flat Float32Array slice.
154
+ *
155
+ * Layout per node (NODE_STRIDE floats):
156
+ * [0..5] – AABB (minX, minY, minZ, maxX, maxY, maxZ)
157
+ * [6] – firstChild index (-1 = leaf / no children)
158
+ * [7] – parent index (-1 = root)
159
+ * [8] – object count
160
+ * [9..] – object indices (MAX_OBJECTS_PER_NODE slots)
161
+ */
162
+ declare const NODE_AABB_OFFSET = 0;
163
+ declare const NODE_FIRST_CHILD_OFFSET = 6;
164
+ declare const NODE_PARENT_OFFSET = 7;
165
+ declare const NODE_OBJECT_COUNT_OFFSET = 8;
166
+ declare const NODE_OBJECTS_OFFSET = 9;
167
+ declare const MAX_OBJECTS_PER_NODE = 8;
168
+ declare const NODE_STRIDE: number;
169
+ /**
170
+ * A pool-backed, zero-GC Octree node store.
171
+ * Each node occupies NODE_STRIDE floats in the underlying Float32Array buffer.
172
+ *
173
+ * When a `SharedArrayBuffer` is provided, the pool's data is accessible from
174
+ * multiple threads (e.g. a Web Worker) with no copying.
175
+ */
176
+ declare class OctreeNodePool {
177
+ private readonly buffer;
178
+ private count;
179
+ constructor(capacity: number, sharedBuffer?: SharedArrayBuffer);
180
+ /**
181
+ * Create an OctreeNodePool backed by a new `SharedArrayBuffer`.
182
+ * Both the pool and the underlying `SharedArrayBuffer` are returned so the
183
+ * caller can transfer the buffer to a `Worker` via `postMessage`.
184
+ */
185
+ static createShared(capacity: number): {
186
+ pool: OctreeNodePool;
187
+ sab: SharedArrayBuffer;
188
+ };
189
+ /** Allocate a new node slot, initialise sentinel values, and return its index. */
190
+ allocate(): number;
191
+ /** Returns the number of allocated nodes. */
192
+ get size(): number;
193
+ /** Reset the pool (all allocations freed, no GC). */
194
+ reset(): void;
195
+ /** Set the AABB bounds for the node at the given index. */
196
+ setAABB(index: number, minX: number, minY: number, minZ: number, maxX: number, maxY: number, maxZ: number): void;
197
+ /** Read a single AABB component (0–5) from the node at the given index. */
198
+ getAABB(index: number, component: number): number;
199
+ /** Set the first-child index for the node (-1 = leaf). */
200
+ setFirstChild(index: number, childIndex: number): void;
201
+ /** Get the first-child index for the node (-1 = leaf). */
202
+ getFirstChild(index: number): number;
203
+ /** Set the parent index for the node (-1 = root). */
204
+ setParent(index: number, parentIndex: number): void;
205
+ /** Get the parent index for the node (-1 = root). */
206
+ getParent(index: number): number;
207
+ /** Return the number of objects stored in the node at the given index. */
208
+ getObjectCount(index: number): number;
209
+ /**
210
+ * Append an object index to the node's object list.
211
+ * Throws a RangeError when MAX_OBJECTS_PER_NODE is exceeded.
212
+ */
213
+ addObject(index: number, objectIndex: number): void;
214
+ /** Return the object index stored at slot `slot` in the given node. */
215
+ getObject(index: number, slot: number): number;
216
+ /** Reset the object count of the given node to zero (does not zero the slots). */
217
+ clearObjects(index: number): void;
218
+ /**
219
+ * Remove a single object index from the node's object list.
220
+ * Uses swap-with-last to avoid shifting. Returns true if found and removed.
221
+ */
222
+ removeObject(index: number, objectIndex: number): boolean;
223
+ }
224
+
225
+ /**
226
+ * Octree with insertion and automatic subdivision.
227
+ *
228
+ * - When a leaf node's object count reaches MAX_OBJECTS_PER_NODE it is
229
+ * subdivided into 8 axis-aligned child octants.
230
+ * - An inserted AABB that fits entirely within a child octant is pushed down.
231
+ * - An AABB that straddles a boundary is kept in the nearest ancestor that
232
+ * fully contains it.
233
+ */
234
+ declare class Octree {
235
+ private readonly nodePool;
236
+ private readonly aabbPool;
237
+ private readonly root;
238
+ /** Tracks which node each object (by AABBPool index) is currently stored in. */
239
+ private readonly objectNodeMap;
240
+ /** Pre-allocated traversal stack reused across raycast calls to avoid GC pressure. */
241
+ private readonly _stack;
242
+ constructor(nodePool: OctreeNodePool, aabbPool: AABBPool);
243
+ /** The index of the root node in the underlying OctreeNodePool. */
244
+ get rootIndex(): number;
245
+ /** Set the world-space AABB that the root node covers. */
246
+ setBounds(minX: number, minY: number, minZ: number, maxX: number, maxY: number, maxZ: number): void;
247
+ /** Insert the AABB at `objectIndex` (in the AABBPool) into the tree. */
248
+ insert(objectIndex: number): void;
249
+ /**
250
+ * Update the AABB at `objectIndex` with new bounds and reposition it in the
251
+ * tree without rebuilding. If the new bounds still fit in the current node
252
+ * the object stays there; otherwise it is removed and re-inserted from the
253
+ * lowest ancestor whose bounds fully contain the new AABB.
254
+ */
255
+ update(objectIndex: number, newMinX: number, newMinY: number, newMinZ: number, newMaxX: number, newMaxY: number, newMaxZ: number): void;
256
+ /**
257
+ * Cast a ray through the octree and return the closest intersecting object.
258
+ *
259
+ * Uses an iterative stack traversal (pre-allocated, no recursion) to avoid
260
+ * GC pressure. Only descends into child nodes whose AABBs are intersected by
261
+ * the ray, providing efficient pruning of non-intersecting subtrees.
262
+ *
263
+ * @param rayBuf Float32Array containing the ray data [ox,oy,oz,dx,dy,dz].
264
+ * @param rayOffset Element offset (in floats) within `rayBuf` to the ray's origin.
265
+ * @returns The closest `{ objectIndex, t }` hit, or `null` if nothing is hit.
266
+ */
267
+ raycast(rayBuf: Float32Array, rayOffset: number): {
268
+ objectIndex: number;
269
+ t: number;
270
+ } | null;
271
+ /**
272
+ * Query the octree for all objects whose AABB overlaps the given axis-aligned
273
+ * box region and return their indices (in the AABBPool).
274
+ *
275
+ * Uses the same pre-allocated iterative stack as `raycast` to avoid GC
276
+ * pressure. Descends only into child nodes whose AABBs overlap the query box,
277
+ * pruning non-intersecting subtrees.
278
+ *
279
+ * @param minX Minimum X of the query box.
280
+ * @param minY Minimum Y of the query box.
281
+ * @param minZ Minimum Z of the query box.
282
+ * @param maxX Maximum X of the query box.
283
+ * @param maxY Maximum Y of the query box.
284
+ * @param maxZ Maximum Z of the query box.
285
+ * @returns Array of AABBPool indices for every object that overlaps the box.
286
+ */
287
+ queryBox(minX: number, minY: number, minZ: number, maxX: number, maxY: number, maxZ: number): number[];
288
+ private insertIntoNode;
289
+ /** Split a leaf node into 8 children and redistribute its objects. */
290
+ private subdivide;
291
+ /** Returns true when the AABB at `objectIndex` is fully contained by `nodeIdx`. */
292
+ private fitsInNode;
293
+ }
294
+
295
+ export { AABBPool, AABB_STRIDE, MAX_OBJECTS_PER_NODE, NODE_AABB_OFFSET, NODE_FIRST_CHILD_OFFSET, NODE_OBJECTS_OFFSET, NODE_OBJECT_COUNT_OFFSET, NODE_PARENT_OFFSET, NODE_STRIDE, ObjectPool, Octree, OctreeNodePool, RAY_STRIDE, RayPool, aabbExpand, aabbIntersects, aabbMerge, rayIntersectsAABB, vec3Cross, vec3Distance, vec3DistanceSq, vec3Dot };
package/dist/index.js ADDED
@@ -0,0 +1,116 @@
1
+ import {
2
+ AABBPool,
3
+ AABB_STRIDE,
4
+ MAX_OBJECTS_PER_NODE,
5
+ NODE_AABB_OFFSET,
6
+ NODE_FIRST_CHILD_OFFSET,
7
+ NODE_OBJECTS_OFFSET,
8
+ NODE_OBJECT_COUNT_OFFSET,
9
+ NODE_PARENT_OFFSET,
10
+ NODE_STRIDE,
11
+ Octree,
12
+ OctreeNodePool,
13
+ RAY_STRIDE,
14
+ RayPool,
15
+ aabbExpand,
16
+ aabbIntersects,
17
+ aabbMerge,
18
+ createLidarProcessor,
19
+ rayIntersectsAABB
20
+ } from "./chunk-JF4RVZK3.js";
21
+
22
+ // src/object-pool.ts
23
+ var ObjectPool = class {
24
+ freeList;
25
+ top;
26
+ /** Total number of slots in the pool. */
27
+ capacity;
28
+ constructor(capacity) {
29
+ this.capacity = capacity;
30
+ this.freeList = new Int32Array(capacity);
31
+ for (let i = 0; i < capacity; i++) {
32
+ this.freeList[i] = capacity - 1 - i;
33
+ }
34
+ this.top = capacity;
35
+ }
36
+ /** Number of indices currently available for acquisition. */
37
+ get available() {
38
+ return this.top;
39
+ }
40
+ /**
41
+ * Acquire a free index from the pool.
42
+ * Returns the index, or `null` when the pool is exhausted.
43
+ */
44
+ acquire() {
45
+ if (this.top === 0) {
46
+ return null;
47
+ }
48
+ this.top -= 1;
49
+ return this.freeList[this.top];
50
+ }
51
+ /**
52
+ * Release a previously acquired index back to the pool.
53
+ * Throws if the index is out of range or the pool is already full.
54
+ */
55
+ release(index) {
56
+ if (index < 0 || index >= this.capacity) {
57
+ throw new RangeError(`ObjectPool.release: index ${index} is out of range [0, ${this.capacity})`);
58
+ }
59
+ if (this.top >= this.capacity) {
60
+ throw new RangeError("ObjectPool.release: pool is already at full capacity");
61
+ }
62
+ this.freeList[this.top] = index;
63
+ this.top += 1;
64
+ }
65
+ };
66
+
67
+ // src/flat-math.ts
68
+ function vec3Dot(buf, i, j) {
69
+ return (buf[i] ?? 0) * (buf[j] ?? 0) + (buf[i + 1] ?? 0) * (buf[j + 1] ?? 0) + (buf[i + 2] ?? 0) * (buf[j + 2] ?? 0);
70
+ }
71
+ function vec3DistanceSq(buf, i, j) {
72
+ const dx = (buf[i] ?? 0) - (buf[j] ?? 0);
73
+ const dy = (buf[i + 1] ?? 0) - (buf[j + 1] ?? 0);
74
+ const dz = (buf[i + 2] ?? 0) - (buf[j + 2] ?? 0);
75
+ return dx * dx + dy * dy + dz * dz;
76
+ }
77
+ function vec3Distance(buf, i, j) {
78
+ return Math.sqrt(vec3DistanceSq(buf, i, j));
79
+ }
80
+ function vec3Cross(out, outOffset, buf, i, j) {
81
+ const ax = buf[i] ?? 0;
82
+ const ay = buf[i + 1] ?? 0;
83
+ const az = buf[i + 2] ?? 0;
84
+ const bx = buf[j] ?? 0;
85
+ const by = buf[j + 1] ?? 0;
86
+ const bz = buf[j + 2] ?? 0;
87
+ out[outOffset] = ay * bz - az * by;
88
+ out[outOffset + 1] = az * bx - ax * bz;
89
+ out[outOffset + 2] = ax * by - ay * bx;
90
+ }
91
+ export {
92
+ AABBPool,
93
+ AABB_STRIDE,
94
+ MAX_OBJECTS_PER_NODE,
95
+ NODE_AABB_OFFSET,
96
+ NODE_FIRST_CHILD_OFFSET,
97
+ NODE_OBJECTS_OFFSET,
98
+ NODE_OBJECT_COUNT_OFFSET,
99
+ NODE_PARENT_OFFSET,
100
+ NODE_STRIDE,
101
+ ObjectPool,
102
+ Octree,
103
+ OctreeNodePool,
104
+ RAY_STRIDE,
105
+ RayPool,
106
+ aabbExpand,
107
+ aabbIntersects,
108
+ aabbMerge,
109
+ createLidarProcessor,
110
+ rayIntersectsAABB,
111
+ vec3Cross,
112
+ vec3Distance,
113
+ vec3DistanceSq,
114
+ vec3Dot
115
+ };
116
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/object-pool.ts","../src/flat-math.ts"],"sourcesContent":["/**\n * A generic Object Pool that manages a fixed set of integer indices.\n *\n * Pre-allocates a free-list on construction so that acquire() and release()\n * operate without any heap allocation.\n */\nexport class ObjectPool {\n private readonly freeList: Int32Array;\n private top: number;\n\n /** Total number of slots in the pool. */\n readonly capacity: number;\n\n constructor(capacity: number) {\n this.capacity = capacity;\n this.freeList = new Int32Array(capacity);\n // Fill free-list in reverse so that the first acquire() returns index 0.\n for (let i = 0; i < capacity; i++) {\n this.freeList[i] = capacity - 1 - i;\n }\n this.top = capacity;\n }\n\n /** Number of indices currently available for acquisition. */\n get available(): number {\n return this.top;\n }\n\n /**\n * Acquire a free index from the pool.\n * Returns the index, or `null` when the pool is exhausted.\n */\n acquire(): number | null {\n if (this.top === 0) {\n return null;\n }\n this.top -= 1;\n return this.freeList[this.top] as number;\n }\n\n /**\n * Release a previously acquired index back to the pool.\n * Throws if the index is out of range or the pool is already full.\n */\n release(index: number): void {\n if (index < 0 || index >= this.capacity) {\n throw new RangeError(`ObjectPool.release: index ${index} is out of range [0, ${this.capacity})`);\n }\n if (this.top >= this.capacity) {\n throw new RangeError('ObjectPool.release: pool is already at full capacity');\n }\n this.freeList[this.top] = index;\n this.top += 1;\n }\n}\n","/**\n * Flat Array Math Utilities\n *\n * Zero-allocation Vec3 math that reads directly from a Float32Array\n * given a start index, without creating any Vector3 objects.\n *\n * All index parameters (`i`, `j`, `outOffset`) are raw flat-array offsets.\n */\n\n/**\n * Compute the dot product of two Vec3s stored in `buf` at offsets `i` and `j`.\n */\nexport function vec3Dot(buf: Float32Array, i: number, j: number): number {\n return (buf[i] ?? 0) * (buf[j] ?? 0) +\n (buf[i + 1] ?? 0) * (buf[j + 1] ?? 0) +\n (buf[i + 2] ?? 0) * (buf[j + 2] ?? 0);\n}\n\n/**\n * Compute the squared distance between two Vec3s stored in `buf` at offsets `i` and `j`.\n */\nexport function vec3DistanceSq(buf: Float32Array, i: number, j: number): number {\n const dx = (buf[i] ?? 0) - (buf[j] ?? 0);\n const dy = (buf[i + 1] ?? 0) - (buf[j + 1] ?? 0);\n const dz = (buf[i + 2] ?? 0) - (buf[j + 2] ?? 0);\n return dx * dx + dy * dy + dz * dz;\n}\n\n/**\n * Compute the Euclidean distance between two Vec3s stored in `buf` at offsets `i` and `j`.\n */\nexport function vec3Distance(buf: Float32Array, i: number, j: number): number {\n return Math.sqrt(vec3DistanceSq(buf, i, j));\n}\n\n/**\n * Compute the cross product of two Vec3s in `buf` at offsets `i` and `j`,\n * and write the result into `out` starting at `outOffset`.\n */\nexport function vec3Cross(\n out: Float32Array,\n outOffset: number,\n buf: Float32Array,\n i: number,\n j: number,\n): void {\n const ax = buf[i] ?? 0;\n const ay = buf[i + 1] ?? 0;\n const az = buf[i + 2] ?? 0;\n const bx = buf[j] ?? 0;\n const by = buf[j + 1] ?? 0;\n const bz = buf[j + 2] ?? 0;\n out[outOffset] = ay * bz - az * by;\n out[outOffset + 1] = az * bx - ax * bz;\n out[outOffset + 2] = ax * by - ay * bx;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAMO,IAAM,aAAN,MAAiB;AAAA,EACL;AAAA,EACT;AAAA;AAAA,EAGC;AAAA,EAET,YAAY,UAAkB;AAC5B,SAAK,WAAW;AAChB,SAAK,WAAW,IAAI,WAAW,QAAQ;AAEvC,aAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AACjC,WAAK,SAAS,CAAC,IAAI,WAAW,IAAI;AAAA,IACpC;AACA,SAAK,MAAM;AAAA,EACb;AAAA;AAAA,EAGA,IAAI,YAAoB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAyB;AACvB,QAAI,KAAK,QAAQ,GAAG;AAClB,aAAO;AAAA,IACT;AACA,SAAK,OAAO;AACZ,WAAO,KAAK,SAAS,KAAK,GAAG;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ,OAAqB;AAC3B,QAAI,QAAQ,KAAK,SAAS,KAAK,UAAU;AACvC,YAAM,IAAI,WAAW,6BAA6B,KAAK,wBAAwB,KAAK,QAAQ,GAAG;AAAA,IACjG;AACA,QAAI,KAAK,OAAO,KAAK,UAAU;AAC7B,YAAM,IAAI,WAAW,sDAAsD;AAAA,IAC7E;AACA,SAAK,SAAS,KAAK,GAAG,IAAI;AAC1B,SAAK,OAAO;AAAA,EACd;AACF;;;AC1CO,SAAS,QAAQ,KAAmB,GAAW,GAAmB;AACvE,UAAQ,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,MAC/B,IAAI,IAAI,CAAC,KAAK,MAAM,IAAI,IAAI,CAAC,KAAK,MAClC,IAAI,IAAI,CAAC,KAAK,MAAM,IAAI,IAAI,CAAC,KAAK;AACvC;AAKO,SAAS,eAAe,KAAmB,GAAW,GAAmB;AAC9E,QAAM,MAAM,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK;AACtC,QAAM,MAAM,IAAI,IAAI,CAAC,KAAK,MAAM,IAAI,IAAI,CAAC,KAAK;AAC9C,QAAM,MAAM,IAAI,IAAI,CAAC,KAAK,MAAM,IAAI,IAAI,CAAC,KAAK;AAC9C,SAAO,KAAK,KAAK,KAAK,KAAK,KAAK;AAClC;AAKO,SAAS,aAAa,KAAmB,GAAW,GAAmB;AAC5E,SAAO,KAAK,KAAK,eAAe,KAAK,GAAG,CAAC,CAAC;AAC5C;AAMO,SAAS,UACd,KACA,WACA,KACA,GACA,GACM;AACN,QAAM,KAAK,IAAI,CAAC,KAAK;AACrB,QAAM,KAAK,IAAI,IAAI,CAAC,KAAK;AACzB,QAAM,KAAK,IAAI,IAAI,CAAC,KAAK;AACzB,QAAM,KAAK,IAAI,CAAC,KAAK;AACrB,QAAM,KAAK,IAAI,IAAI,CAAC,KAAK;AACzB,QAAM,KAAK,IAAI,IAAI,CAAC,KAAK;AACzB,MAAI,SAAS,IAAI,KAAK,KAAK,KAAK;AAChC,MAAI,YAAY,CAAC,IAAI,KAAK,KAAK,KAAK;AACpC,MAAI,YAAY,CAAC,IAAI,KAAK,KAAK,KAAK;AACtC;","names":[]}