@kgdiff/layout 0.0.0-stage → 0.2.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 (113) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +46 -2
  3. package/dist/components.d.ts +11 -0
  4. package/dist/components.d.ts.map +1 -0
  5. package/dist/components.js +56 -0
  6. package/dist/components.js.map +1 -0
  7. package/dist/engine.d.ts +20 -0
  8. package/dist/engine.d.ts.map +1 -0
  9. package/dist/engine.js +336 -0
  10. package/dist/engine.js.map +1 -0
  11. package/dist/extend.d.ts +7 -0
  12. package/dist/extend.d.ts.map +1 -0
  13. package/dist/extend.js +68 -0
  14. package/dist/extend.js.map +1 -0
  15. package/dist/forces/collide-rect.d.ts +50 -0
  16. package/dist/forces/collide-rect.d.ts.map +1 -0
  17. package/dist/forces/collide-rect.js +310 -0
  18. package/dist/forces/collide-rect.js.map +1 -0
  19. package/dist/forces/free-spot.d.ts +40 -0
  20. package/dist/forces/free-spot.d.ts.map +1 -0
  21. package/dist/forces/free-spot.js +189 -0
  22. package/dist/forces/free-spot.js.map +1 -0
  23. package/dist/forces/params.d.ts +38 -0
  24. package/dist/forces/params.d.ts.map +1 -0
  25. package/dist/forces/params.js +55 -0
  26. package/dist/forces/params.js.map +1 -0
  27. package/dist/forces/springs.d.ts +20 -0
  28. package/dist/forces/springs.d.ts.map +1 -0
  29. package/dist/forces/springs.js +34 -0
  30. package/dist/forces/springs.js.map +1 -0
  31. package/dist/geometry.d.ts +21 -0
  32. package/dist/geometry.d.ts.map +1 -0
  33. package/dist/geometry.js +39 -0
  34. package/dist/geometry.js.map +1 -0
  35. package/dist/graph.d.ts +38 -0
  36. package/dist/graph.d.ts.map +1 -0
  37. package/dist/graph.js +82 -0
  38. package/dist/graph.js.map +1 -0
  39. package/dist/index.d.ts +162 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +87 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/init.d.ts +28 -0
  44. package/dist/init.d.ts.map +1 -0
  45. package/dist/init.js +196 -0
  46. package/dist/init.js.map +1 -0
  47. package/dist/json.d.ts +4 -0
  48. package/dist/json.d.ts.map +1 -0
  49. package/dist/json.js +112 -0
  50. package/dist/json.js.map +1 -0
  51. package/dist/layout.d.ts +7 -0
  52. package/dist/layout.d.ts.map +1 -0
  53. package/dist/layout.js +70 -0
  54. package/dist/layout.js.map +1 -0
  55. package/dist/math.d.ts +29 -0
  56. package/dist/math.d.ts.map +1 -0
  57. package/dist/math.js +91 -0
  58. package/dist/math.js.map +1 -0
  59. package/dist/options.d.ts +43 -0
  60. package/dist/options.d.ts.map +1 -0
  61. package/dist/options.js +76 -0
  62. package/dist/options.js.map +1 -0
  63. package/dist/pack.d.ts +43 -0
  64. package/dist/pack.d.ts.map +1 -0
  65. package/dist/pack.js +168 -0
  66. package/dist/pack.js.map +1 -0
  67. package/dist/prng.d.ts +20 -0
  68. package/dist/prng.d.ts.map +1 -0
  69. package/dist/prng.js +53 -0
  70. package/dist/prng.js.map +1 -0
  71. package/dist/result.d.ts +20 -0
  72. package/dist/result.d.ts.map +1 -0
  73. package/dist/result.js +40 -0
  74. package/dist/result.js.map +1 -0
  75. package/dist/scope.d.ts +25 -0
  76. package/dist/scope.d.ts.map +1 -0
  77. package/dist/scope.js +71 -0
  78. package/dist/scope.js.map +1 -0
  79. package/dist/simulate.d.ts +64 -0
  80. package/dist/simulate.d.ts.map +1 -0
  81. package/dist/simulate.js +247 -0
  82. package/dist/simulate.js.map +1 -0
  83. package/dist/text-metrics.d.ts +32 -0
  84. package/dist/text-metrics.d.ts.map +1 -0
  85. package/dist/text-metrics.js +153 -0
  86. package/dist/text-metrics.js.map +1 -0
  87. package/dist/union.d.ts +32 -0
  88. package/dist/union.d.ts.map +1 -0
  89. package/dist/union.js +106 -0
  90. package/dist/union.js.map +1 -0
  91. package/package.json +52 -3
  92. package/src/components.ts +56 -0
  93. package/src/engine.ts +444 -0
  94. package/src/extend.ts +75 -0
  95. package/src/forces/collide-rect.ts +385 -0
  96. package/src/forces/free-spot.ts +243 -0
  97. package/src/forces/params.ts +88 -0
  98. package/src/forces/springs.ts +50 -0
  99. package/src/geometry.ts +66 -0
  100. package/src/graph.ts +120 -0
  101. package/src/index.ts +193 -0
  102. package/src/init.ts +246 -0
  103. package/src/json.ts +131 -0
  104. package/src/layout.ts +87 -0
  105. package/src/math.ts +91 -0
  106. package/src/options.ts +153 -0
  107. package/src/pack.ts +228 -0
  108. package/src/prng.ts +59 -0
  109. package/src/result.ts +63 -0
  110. package/src/scope.ts +86 -0
  111. package/src/simulate.ts +328 -0
  112. package/src/text-metrics.ts +157 -0
  113. package/src/union.ts +127 -0
@@ -0,0 +1,50 @@
1
+ import type { SimNode } from '../simulate.js';
2
+ export interface CollisionBoxes {
3
+ /** Half extents of each node's box, by `SimNode.index`. */
4
+ readonly halfWidth: Float64Array;
5
+ readonly halfHeight: Float64Array;
6
+ /** Box center minus node center (labels sit below, so usually positive). */
7
+ readonly offsetY: Float64Array;
8
+ /** 0 = immovable (fixed node). */
9
+ readonly invMass: Float64Array;
10
+ }
11
+ /** Reusable buffers for one node set. */
12
+ export interface CollisionScratch {
13
+ readonly indices: readonly number[];
14
+ readonly cx: Float64Array;
15
+ readonly cy: Float64Array;
16
+ readonly posX: Float64Array;
17
+ readonly negX: Float64Array;
18
+ readonly posY: Float64Array;
19
+ readonly negY: Float64Array;
20
+ }
21
+ export declare function collisionScratch(n: number): CollisionScratch;
22
+ /**
23
+ * Collision as a simulation force: overlapping boxes (at predicted positions x + vx) get their
24
+ * velocities pushed apart by `strength` × the penetration along the separating axis.
25
+ */
26
+ export declare function collideVelocities(nodes: readonly SimNode[], boxes: CollisionBoxes, padding: number, strength: number, scratch?: CollisionScratch): void;
27
+ export interface OverlapResult {
28
+ readonly passes: number;
29
+ /** 1 for nodes that took part in an overlap in the last pass. */
30
+ readonly unresolved: Uint8Array;
31
+ }
32
+ /**
33
+ * Separate overlapping boxes by moving positions, pass after pass, until none overlap or
34
+ * `maxPasses` is reached. Each pass is a Jacobi step: every node moves by its largest push in
35
+ * each direction (not the sum, which would overshoot when several neighbours push the same way).
36
+ * Only nodes that moved in the previous pass (or `active` ones, initially) are queried; the
37
+ * quadtree is rebuilt only when some node has drifted more than a few units since the last build
38
+ * (the query is widened by that drift), so late passes over a few stubborn pairs are cheap.
39
+ *
40
+ * Local pushes clear scattered overlaps in a few passes but diffuse slowly through a jam (a
41
+ * crowded region that needs more area). When nothing is fixed and the overlap count stalls, the
42
+ * layout is scaled up about its centroid (by 3–15%, more for heavier jams; every 3 passes by up
43
+ * to 25% while more pairs than half the nodes overlap): uniform scaling keeps the picture and
44
+ * frees room everywhere. With fixed nodes, overlaps may remain (a free node wedged between fixed
45
+ * ones is left to the caller).
46
+ *
47
+ * Returns the passes used and the nodes still involved in an overlap (empty when all clear).
48
+ */
49
+ export declare function removeOverlaps(nodes: readonly SimNode[], boxes: CollisionBoxes, padding: number, maxPasses: number, initiallyActive?: Uint8Array): OverlapResult;
50
+ //# sourceMappingURL=collide-rect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collide-rect.d.ts","sourceRoot":"","sources":["../../src/forces/collide-rect.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE9C,MAAM,WAAW,cAAc;IAC7B,2DAA2D;IAC3D,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC;IAClC,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,kCAAkC;IAClC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;CAChC;AAkJD,yCAAyC;AACzC,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,EAAE,EAAE,YAAY,CAAC;IAC1B,QAAQ,CAAC,EAAE,EAAE,YAAY,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;CAC7B;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAU5D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,SAAS,OAAO,EAAE,EACzB,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,gBAAiD,GACzD,IAAI,CA2BN;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,iEAAiE;IACjE,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;CACjC;AASD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,SAAS,OAAO,EAAE,EACzB,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,eAAe,CAAC,EAAE,UAAU,GAC3B,aAAa,CAkGf"}
@@ -0,0 +1,310 @@
1
+ /**
2
+ * Rectangle-vs-rectangle collision over node + label boxes, accelerated with a quadtree.
3
+ *
4
+ * Every node owns one axis-aligned box (its circle plus the label block centered below it).
5
+ * Overlapping pairs are separated along the axis of least penetration (the minimum translation
6
+ * vector), shared in proportion to inverse mass so hubs and fixed nodes stay put. Wide label
7
+ * boxes therefore slide sideways past each other while stacked nodes separate vertically.
8
+ *
9
+ * Box centers go into a d3 quadtree; every quadtree cell records the largest half extents below
10
+ * it, so a query for box i only descends into cells whose content could reach it. Traversal uses
11
+ * an explicit, reused stack (no per-cell allocation, unlike `quadtree.visit`).
12
+ *
13
+ * Two entry points share the pair search:
14
+ * - `collideVelocities`: a force acting on predicted positions (x + vx) during the simulation;
15
+ * - `removeOverlaps`: position-level passes after the simulation until no pair overlaps.
16
+ */
17
+ import { quadtree } from 'd3-quadtree';
18
+ const isLeaf = (cell) => 'data' in cell;
19
+ /** Post-order: record max half extents on every cell. */
20
+ function prepare(cell, hw, hh) {
21
+ let mw = 0;
22
+ let mh = 0;
23
+ if (isLeaf(cell)) {
24
+ let leaf = cell;
25
+ while (leaf !== undefined) {
26
+ mw = Math.max(mw, hw[leaf.data]);
27
+ mh = Math.max(mh, hh[leaf.data]);
28
+ leaf = leaf.next;
29
+ }
30
+ }
31
+ else {
32
+ for (let k = 0; k < 4; k++) {
33
+ const child = cell[k];
34
+ if (child === undefined)
35
+ continue;
36
+ prepare(child, hw, hh);
37
+ mw = Math.max(mw, child.mw ?? 0);
38
+ mh = Math.max(mh, child.mh ?? 0);
39
+ }
40
+ }
41
+ cell.mw = mw;
42
+ cell.mh = mh;
43
+ }
44
+ function buildIndex(indices, cx, cy, boxes) {
45
+ const tree = quadtree()
46
+ .x((i) => cx[i])
47
+ .y((i) => cy[i])
48
+ .addAll(indices);
49
+ const root = tree.root();
50
+ const extent = tree.extent();
51
+ if (root === undefined || extent === undefined)
52
+ return undefined;
53
+ prepare(root, boxes.halfWidth, boxes.halfHeight);
54
+ return { root, x0: extent[0][0], y0: extent[0][1], x1: extent[1][0], y1: extent[1][1] };
55
+ }
56
+ /** Reused traversal stacks (no allocation per query). */
57
+ const cellStack = [];
58
+ const rectStack = [];
59
+ /**
60
+ * Visit every pair (i, j) whose padded boxes overlap, each pair once. Box centers are the
61
+ * current `cx`, `cy`; `index` may have been built from older centers, in which case `slack` must
62
+ * bound how far any center has moved since (it widens the pruning test, so the search stays
63
+ * exact). With `active`, only pairs with at least one active node are visited.
64
+ */
65
+ function forEachOverlap(index, n, cx, cy, boxes, padding, slack, visit, active) {
66
+ const { halfWidth: hw, halfHeight: hh } = boxes;
67
+ const cells = cellStack;
68
+ const rect = rectStack;
69
+ for (let i = 0; i < n; i++) {
70
+ if (active !== undefined && !active[i])
71
+ continue;
72
+ const xi = cx[i];
73
+ const yi = cy[i];
74
+ const hwi = hw[i] + padding;
75
+ const hhi = hh[i] + padding;
76
+ cells.push(index.root);
77
+ rect.push(index.x0, index.y0, index.x1, index.y1);
78
+ while (cells.length > 0) {
79
+ const cell = cells.pop();
80
+ const y1 = rect.pop();
81
+ const x1 = rect.pop();
82
+ const y0 = rect.pop();
83
+ const x0 = rect.pop();
84
+ if (isLeaf(cell)) {
85
+ let leaf = cell;
86
+ while (leaf !== undefined) {
87
+ const j = leaf.data;
88
+ leaf = leaf.next;
89
+ // Each pair once: from its lower index, or from its only active member.
90
+ if (j === i || (j < i && (active === undefined || active[j])))
91
+ continue;
92
+ const dx = cx[j] - xi;
93
+ const ox = hwi + hw[j] - Math.abs(dx);
94
+ if (ox <= 0)
95
+ continue;
96
+ const dy = cy[j] - yi;
97
+ const oy = hhi + hh[j] - Math.abs(dy);
98
+ if (oy <= 0)
99
+ continue;
100
+ visit(i, j, ox, oy, dx, dy);
101
+ }
102
+ continue;
103
+ }
104
+ const rx = hwi + (cell.mw ?? 0) + slack;
105
+ const ry = hhi + (cell.mh ?? 0) + slack;
106
+ if (x0 > xi + rx || x1 < xi - rx || y0 > yi + ry || y1 < yi - ry)
107
+ continue;
108
+ const xm = (x0 + x1) / 2;
109
+ const ym = (y0 + y1) / 2;
110
+ const c0 = cell[0];
111
+ const c1 = cell[1];
112
+ const c2 = cell[2];
113
+ const c3 = cell[3];
114
+ if (c0 !== undefined) {
115
+ cells.push(c0);
116
+ rect.push(x0, y0, xm, ym);
117
+ }
118
+ if (c1 !== undefined) {
119
+ cells.push(c1);
120
+ rect.push(xm, y0, x1, ym);
121
+ }
122
+ if (c2 !== undefined) {
123
+ cells.push(c2);
124
+ rect.push(x0, ym, xm, y1);
125
+ }
126
+ if (c3 !== undefined) {
127
+ cells.push(c3);
128
+ rect.push(xm, ym, x1, y1);
129
+ }
130
+ }
131
+ }
132
+ }
133
+ export function collisionScratch(n) {
134
+ return {
135
+ indices: Array.from({ length: n }, (_, i) => i),
136
+ cx: new Float64Array(n),
137
+ cy: new Float64Array(n),
138
+ posX: new Float64Array(n),
139
+ negX: new Float64Array(n),
140
+ posY: new Float64Array(n),
141
+ negY: new Float64Array(n),
142
+ };
143
+ }
144
+ /**
145
+ * Collision as a simulation force: overlapping boxes (at predicted positions x + vx) get their
146
+ * velocities pushed apart by `strength` × the penetration along the separating axis.
147
+ */
148
+ export function collideVelocities(nodes, boxes, padding, strength, scratch = collisionScratch(nodes.length)) {
149
+ const { cx, cy } = scratch;
150
+ const { invMass, offsetY } = boxes;
151
+ for (const node of nodes) {
152
+ cx[node.index] = node.x + node.vx;
153
+ cy[node.index] = node.y + node.vy + offsetY[node.index];
154
+ }
155
+ const index = buildIndex(scratch.indices, cx, cy, boxes);
156
+ if (index === undefined)
157
+ return;
158
+ forEachOverlap(index, nodes.length, cx, cy, boxes, padding, 0, (i, j, ox, oy, dx, dy) => {
159
+ const total = invMass[i] + invMass[j];
160
+ if (total === 0)
161
+ return;
162
+ const shareI = invMass[i] / total;
163
+ const shareJ = invMass[j] / total;
164
+ const a = nodes[i];
165
+ const b = nodes[j];
166
+ // Push along the axis of least penetration; coincident centers: i goes left / up.
167
+ if (ox < oy) {
168
+ const push = (dx < 0 ? -ox : ox) * strength;
169
+ a.vx -= push * shareI;
170
+ b.vx += push * shareJ;
171
+ }
172
+ else {
173
+ const push = (dy < 0 ? -oy : oy) * strength;
174
+ a.vy -= push * shareI;
175
+ b.vy += push * shareJ;
176
+ }
177
+ });
178
+ }
179
+ /** Jacobi passes between two checks for a stalled jam. */
180
+ const STALL_WINDOW = 8;
181
+ /** Passes between two expansions while the jam is heavy. */
182
+ const HEAVY_WINDOW = 3;
183
+ /** Rebuild the quadtree once some node has drifted this far since the last build. */
184
+ const REBUILD_DRIFT = 8;
185
+ /**
186
+ * Separate overlapping boxes by moving positions, pass after pass, until none overlap or
187
+ * `maxPasses` is reached. Each pass is a Jacobi step: every node moves by its largest push in
188
+ * each direction (not the sum, which would overshoot when several neighbours push the same way).
189
+ * Only nodes that moved in the previous pass (or `active` ones, initially) are queried; the
190
+ * quadtree is rebuilt only when some node has drifted more than a few units since the last build
191
+ * (the query is widened by that drift), so late passes over a few stubborn pairs are cheap.
192
+ *
193
+ * Local pushes clear scattered overlaps in a few passes but diffuse slowly through a jam (a
194
+ * crowded region that needs more area). When nothing is fixed and the overlap count stalls, the
195
+ * layout is scaled up about its centroid (by 3–15%, more for heavier jams; every 3 passes by up
196
+ * to 25% while more pairs than half the nodes overlap): uniform scaling keeps the picture and
197
+ * frees room everywhere. With fixed nodes, overlaps may remain (a free node wedged between fixed
198
+ * ones is left to the caller).
199
+ *
200
+ * Returns the passes used and the nodes still involved in an overlap (empty when all clear).
201
+ */
202
+ export function removeOverlaps(nodes, boxes, padding, maxPasses, initiallyActive) {
203
+ const n = nodes.length;
204
+ const scratch = collisionScratch(n);
205
+ const { cx, cy, posX, negX, posY, negY } = scratch;
206
+ const { invMass, offsetY } = boxes;
207
+ const expandable = invMass.every((m) => m > 0);
208
+ let active = initiallyActive ?? new Uint8Array(n).fill(1);
209
+ let moved = new Uint8Array(n);
210
+ const drift = new Float64Array(n);
211
+ let slack = 0;
212
+ let index;
213
+ let lastCheck = Number.POSITIVE_INFINITY;
214
+ // A hair more than the overlap, so rounding to 0.01 cannot leave boxes touching.
215
+ const epsilon = 0.02;
216
+ for (let pass = 0; pass < maxPasses; pass++) {
217
+ for (const node of nodes) {
218
+ cx[node.index] = node.x;
219
+ cy[node.index] = node.y + offsetY[node.index];
220
+ }
221
+ if (index === undefined || slack > REBUILD_DRIFT) {
222
+ index = buildIndex(scratch.indices, cx, cy, boxes);
223
+ if (index === undefined)
224
+ return { passes: pass, unresolved: new Uint8Array(n) };
225
+ drift.fill(0);
226
+ slack = 0;
227
+ }
228
+ posX.fill(0);
229
+ negX.fill(0);
230
+ posY.fill(0);
231
+ negY.fill(0);
232
+ let overlaps = 0;
233
+ forEachOverlap(index, n, cx, cy, boxes, padding, slack, (i, j, ox, oy, dx, dy) => {
234
+ const total = invMass[i] + invMass[j];
235
+ if (total === 0)
236
+ return;
237
+ overlaps++;
238
+ const shareI = invMass[i] / total;
239
+ const shareJ = invMass[j] / total;
240
+ if (ox < oy) {
241
+ const push = ox + epsilon;
242
+ // j right of i (or coincident and i < j): i moves left, j moves right.
243
+ const jRight = dx > 0 || (dx === 0 && i < j);
244
+ const left = jRight ? i : j;
245
+ const right = jRight ? j : i;
246
+ negX[left] = Math.min(negX[left], -push * (left === i ? shareI : shareJ));
247
+ posX[right] = Math.max(posX[right], push * (right === i ? shareI : shareJ));
248
+ }
249
+ else {
250
+ const push = oy + epsilon;
251
+ const jDown = dy > 0 || (dy === 0 && i < j);
252
+ const up = jDown ? i : j;
253
+ const down = jDown ? j : i;
254
+ negY[up] = Math.min(negY[up], -push * (up === i ? shareI : shareJ));
255
+ posY[down] = Math.max(posY[down], push * (down === i ? shareI : shareJ));
256
+ }
257
+ }, active);
258
+ if (overlaps === 0)
259
+ return { passes: pass, unresolved: new Uint8Array(n) };
260
+ moved.fill(0);
261
+ for (const node of nodes) {
262
+ const k = node.index;
263
+ // Pushes from opposite sides may cancel: the node is still involved, so it stays active.
264
+ if (posX[k] !== 0 || negX[k] !== 0 || posY[k] !== 0 || negY[k] !== 0) {
265
+ const mx = posX[k] + negX[k];
266
+ const my = posY[k] + negY[k];
267
+ node.x += mx;
268
+ node.y += my;
269
+ moved[k] = 1;
270
+ const d = drift[k] + Math.max(Math.abs(mx), Math.abs(my));
271
+ drift[k] = d;
272
+ if (d > slack)
273
+ slack = d;
274
+ }
275
+ }
276
+ [active, moved] = [moved, active];
277
+ if (expandable && overlaps > n / 2 && (pass + 1) % HEAVY_WINDOW === 0) {
278
+ // A heavy jam (more overlapping pairs than half the nodes): do not wait for a stall.
279
+ expand(nodes, 1 + Math.min(0.25, (0.05 * overlaps) / n));
280
+ active.fill(1);
281
+ index = undefined;
282
+ lastCheck = Number.POSITIVE_INFINITY;
283
+ }
284
+ else if ((pass + 1) % STALL_WINDOW === 0) {
285
+ // A jam: local moves stopped making progress.
286
+ if (expandable && overlaps > 0.7 * lastCheck) {
287
+ expand(nodes, 1 + Math.min(0.15, Math.max(0.03, (0.05 * overlaps) / n)));
288
+ active.fill(1);
289
+ index = undefined;
290
+ }
291
+ lastCheck = overlaps;
292
+ }
293
+ }
294
+ return { passes: maxPasses, unresolved: active };
295
+ }
296
+ function expand(nodes, factor) {
297
+ let mx = 0;
298
+ let my = 0;
299
+ for (const node of nodes) {
300
+ mx += node.x;
301
+ my += node.y;
302
+ }
303
+ mx /= nodes.length;
304
+ my /= nodes.length;
305
+ for (const node of nodes) {
306
+ node.x = mx + (node.x - mx) * factor;
307
+ node.y = my + (node.y - my) * factor;
308
+ }
309
+ }
310
+ //# sourceMappingURL=collide-rect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collide-rect.js","sourceRoot":"","sources":["../../src/forces/collide-rect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Final placement touches that look for free spots instead of pushing.
3
+ *
4
+ * - `dockPartners`: the weak partner springs (docs/algorithms.md §12) bring merge sources towards
5
+ * their target, but many-body repulsion and label boxes keep the pair roughly an edge length
6
+ * apart. For replay (sources travel into the target, split targets emerge from their source)
7
+ * and for reading the overlay (the ghost sits right next to what it became), a mover farther
8
+ * than `maxDistance` from its anchor moves to the best free spot around the anchor.
9
+ * - `settleOverlapping`: around fixed nodes, a free node can end up wedged where pushing cannot
10
+ * free it. It moves to the free spot nearest to its neighbours instead.
11
+ *
12
+ * Both test candidate spots (16 directions × a few rings) against the boxes near the searched
13
+ * area, collected once per node; they only run for the few nodes that need them.
14
+ */
15
+ import type { SimNode } from '../simulate.js';
16
+ import type { CollisionBoxes } from './collide-rect.js';
17
+ import type { Spring } from './springs.js';
18
+ /**
19
+ * Dock merge sources / split targets (`mover`) farther than `maxDistance` from their partner.
20
+ * Candidate spots touch the anchor's box in 16 directions, on 5 rings; the winner minimizes the
21
+ * distance to the anchor plus 0.3 × the distance travelled (so the mover stays on the side its
22
+ * edges come from). A spot occupied only by movable nodes competes with a penalty of
23
+ * 0.4 × `maxDistance`; when it wins, the caller pushes those nodes aside (`removeOverlaps` with
24
+ * docked pairs pinned). Only spots closer to the anchor than the mover's current position count.
25
+ *
26
+ * Returns the sim indices of docked movers and their anchors (to pin while making room).
27
+ */
28
+ export declare function dockPartners(nodes: readonly SimNode[], springs: readonly Spring[], boxes: CollisionBoxes, padding: number, maxDistance: number): number[];
29
+ /**
30
+ * Move every movable node whose box still overlaps another to the free spot nearest to `home(k)`
31
+ * (its neighbours' barycenter). Candidates lie on square rings of a lattice around home (spacing
32
+ * ≈ the node's box height, so gaps between neighbours are found at any radius; exact arithmetic
33
+ * only); the first ring with a free spot wins, and on it the spot closest to home. Nodes are
34
+ * processed in index order.
35
+ */
36
+ export declare function settleOverlapping(nodes: readonly SimNode[], boxes: CollisionBoxes, padding: number, home: (index: number) => {
37
+ readonly x: number;
38
+ readonly y: number;
39
+ }): void;
40
+ //# sourceMappingURL=free-spot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"free-spot.d.ts","sourceRoot":"","sources":["../../src/forces/free-spot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAoF3C;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,SAAS,OAAO,EAAE,EACzB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,GAClB,MAAM,EAAE,CAgEV;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,SAAS,OAAO,EAAE,EACzB,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK;IAAE,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAClE,IAAI,CAgDN"}
@@ -0,0 +1,189 @@
1
+ /** Unit vectors every 22.5°, starting straight down (below the anchor's label), exact literals. */
2
+ const C1 = 0.9238795325112867;
3
+ const S1 = 0.3826834323650898;
4
+ const D = Math.SQRT1_2;
5
+ const DIRECTIONS = [
6
+ [0, 1],
7
+ [S1, C1],
8
+ [D, D],
9
+ [C1, S1],
10
+ [1, 0],
11
+ [C1, -S1],
12
+ [D, -D],
13
+ [S1, -C1],
14
+ [0, -1],
15
+ [-S1, -C1],
16
+ [-D, -D],
17
+ [-C1, -S1],
18
+ [-1, 0],
19
+ [-C1, S1],
20
+ [-D, D],
21
+ [-S1, C1],
22
+ ];
23
+ const DOCK_RINGS = [1, 1.35, 1.7, 2.1, 2.6];
24
+ /** Extra score (× maxDistance) charged to a spot that other nodes must vacate. */
25
+ const OCCUPIED_PENALTY = 0.4;
26
+ /** Square lattice rings searched around a wedged node (ring k at k × step from home). */
27
+ const SETTLE_RINGS = 32;
28
+ const distance = (ax, ay, bx, by) => Math.sqrt((ax - bx) * (ax - bx) + (ay - by) * (ay - by));
29
+ /**
30
+ * The nodes whose boxes could touch node `m`'s box anywhere within `radius` of (cx, cy): the
31
+ * candidate search then only tests these (O(n) once per searched node, not per candidate).
32
+ */
33
+ function nearby(nodes, boxes, padding, m, cx, cy, radius) {
34
+ const { halfWidth: hw, halfHeight: hh, offsetY: oy } = boxes;
35
+ const out = [];
36
+ for (const other of nodes) {
37
+ const j = other.index;
38
+ if (j === m)
39
+ continue;
40
+ if (Math.abs(other.x - cx) > radius + hw[m] + hw[j] + padding)
41
+ continue;
42
+ const dy = other.y + oy[j] - (cy + oy[m]);
43
+ if (Math.abs(dy) > radius + hh[m] + hh[j] + padding)
44
+ continue;
45
+ out.push(other);
46
+ }
47
+ return out;
48
+ }
49
+ /**
50
+ * True when node `m`'s padded box centered at (x, y) overlaps none of `others`' boxes, or (with
51
+ * `blocking`) none for which `blocking(j)` holds.
52
+ */
53
+ function isFree(others, boxes, padding, m, x, y, blocking) {
54
+ const { halfWidth: hw, halfHeight: hh, offsetY: oy } = boxes;
55
+ const cy = y + oy[m];
56
+ for (const other of others) {
57
+ const j = other.index;
58
+ if (j === m || (blocking !== undefined && !blocking(j)))
59
+ continue;
60
+ if (Math.abs(other.x - x) >= hw[m] + hw[j] + padding)
61
+ continue;
62
+ if (Math.abs(other.y + oy[j] - cy) >= hh[m] + hh[j] + padding)
63
+ continue;
64
+ return false;
65
+ }
66
+ return true;
67
+ }
68
+ /**
69
+ * Dock merge sources / split targets (`mover`) farther than `maxDistance` from their partner.
70
+ * Candidate spots touch the anchor's box in 16 directions, on 5 rings; the winner minimizes the
71
+ * distance to the anchor plus 0.3 × the distance travelled (so the mover stays on the side its
72
+ * edges come from). A spot occupied only by movable nodes competes with a penalty of
73
+ * 0.4 × `maxDistance`; when it wins, the caller pushes those nodes aside (`removeOverlaps` with
74
+ * docked pairs pinned). Only spots closer to the anchor than the mover's current position count.
75
+ *
76
+ * Returns the sim indices of docked movers and their anchors (to pin while making room).
77
+ */
78
+ export function dockPartners(nodes, springs, boxes, padding, maxDistance) {
79
+ const { halfWidth: hw, halfHeight: hh, offsetY: oy, invMass } = boxes;
80
+ const top = (i) => oy[i] - hh[i];
81
+ const bottom = (i) => oy[i] + hh[i];
82
+ const gap = padding + 0.05;
83
+ const pinned = new Set();
84
+ const immovable = (j) => invMass[j] === 0 || pinned.has(j);
85
+ for (const { mover, anchor } of springs) {
86
+ const m = nodes[mover];
87
+ const a = nodes[anchor];
88
+ if (m === undefined || a === undefined || immovable(mover))
89
+ continue;
90
+ const current = distance(m.x, m.y, a.x, a.y);
91
+ if (current <= maxDistance)
92
+ continue;
93
+ const reachX = (hw[anchor] + hw[mover] + gap) * DOCK_RINGS[DOCK_RINGS.length - 1];
94
+ const reachY = (Math.max(bottom(anchor) - top(mover), bottom(mover) - top(anchor)) + gap) *
95
+ DOCK_RINGS[DOCK_RINGS.length - 1];
96
+ const others = nearby(nodes, boxes, padding, mover, a.x, a.y, Math.max(reachX, reachY));
97
+ let free;
98
+ let occupied;
99
+ for (const ring of DOCK_RINGS) {
100
+ for (const [ux, uy] of DIRECTIONS) {
101
+ const tx = ux === 0 ? Number.POSITIVE_INFINITY : (hw[anchor] + hw[mover] + gap) / Math.abs(ux);
102
+ const ty = uy === 0
103
+ ? Number.POSITIVE_INFINITY
104
+ : uy > 0
105
+ ? (bottom(anchor) + gap - top(mover)) / uy
106
+ : (bottom(mover) + gap - top(anchor)) / -uy;
107
+ const t = Math.min(tx, ty) * ring;
108
+ const x = a.x + ux * t;
109
+ const y = a.y + uy * t;
110
+ const toAnchor = distance(x, y, a.x, a.y);
111
+ if (toAnchor >= current)
112
+ continue;
113
+ const score = toAnchor + 0.3 * distance(x, y, m.x, m.y);
114
+ if (isFree(others, boxes, padding, mover, x, y)) {
115
+ if (free === undefined || score < free.score - 1e-9)
116
+ free = { x, y, score };
117
+ }
118
+ else if ((occupied === undefined || score < occupied.score - 1e-9) &&
119
+ isFree(others, boxes, padding, mover, x, y, immovable)) {
120
+ occupied = { x, y, score };
121
+ }
122
+ }
123
+ }
124
+ // An occupied spot must be clearly better to be worth pushing the neighbours aside.
125
+ const penalty = OCCUPIED_PENALTY * maxDistance;
126
+ const best = occupied !== undefined && (free === undefined || occupied.score + penalty < free.score)
127
+ ? occupied
128
+ : free;
129
+ if (best !== undefined) {
130
+ m.x = best.x;
131
+ m.y = best.y;
132
+ m.vx = 0;
133
+ m.vy = 0;
134
+ pinned.add(mover);
135
+ pinned.add(anchor);
136
+ }
137
+ }
138
+ return [...pinned].sort((p, q) => p - q);
139
+ }
140
+ /**
141
+ * Move every movable node whose box still overlaps another to the free spot nearest to `home(k)`
142
+ * (its neighbours' barycenter). Candidates lie on square rings of a lattice around home (spacing
143
+ * ≈ the node's box height, so gaps between neighbours are found at any radius; exact arithmetic
144
+ * only); the first ring with a free spot wins, and on it the spot closest to home. Nodes are
145
+ * processed in index order.
146
+ */
147
+ export function settleOverlapping(nodes, boxes, padding, home) {
148
+ const { halfHeight: hh, invMass } = boxes;
149
+ for (const node of nodes) {
150
+ const k = node.index;
151
+ if (invMass[k] === 0)
152
+ continue;
153
+ if (isFree(nearby(nodes, boxes, padding, k, node.x, node.y, 0), boxes, padding, k, node.x, node.y)) {
154
+ continue;
155
+ }
156
+ const center = home(k);
157
+ const step = Math.max(12, hh[k] + padding);
158
+ // Nearby nodes for the next 8 rings at a time, so the search stays local.
159
+ let others = [];
160
+ for (let ring = 1; ring <= SETTLE_RINGS; ring++) {
161
+ if ((ring - 1) % 8 === 0) {
162
+ others = nearby(nodes, boxes, padding, k, center.x, center.y, step * (ring + 7) * Math.SQRT2);
163
+ }
164
+ let best;
165
+ const consider = (x, y) => {
166
+ const d = distance(x, y, center.x, center.y);
167
+ if (best !== undefined && d >= best.d - 1e-9)
168
+ return;
169
+ if (isFree(others, boxes, padding, k, x, y))
170
+ best = { x, y, d };
171
+ };
172
+ const r = ring * step;
173
+ for (let i = -ring; i <= ring; i++) {
174
+ consider(center.x + i * step, center.y - r);
175
+ consider(center.x + i * step, center.y + r);
176
+ }
177
+ for (let j = 1 - ring; j < ring; j++) {
178
+ consider(center.x - r, center.y + j * step);
179
+ consider(center.x + r, center.y + j * step);
180
+ }
181
+ if (best !== undefined) {
182
+ node.x = best.x;
183
+ node.y = best.y;
184
+ break;
185
+ }
186
+ }
187
+ }
188
+ }
189
+ //# sourceMappingURL=free-spot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"free-spot.js","sourceRoot":"","sources":["../../src/forces/free-spot.ts"],"names":[],"mappings":"AAkBA,mGAAmG;AACnG,MAAM,EAAE,GAAG,kBAAkB,CAAC;AAC9B,MAAM,EAAE,GAAG,kBAAkB,CAAC;AAC9B,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;AACvB,MAAM,UAAU,GAA2C;IACzD,CAAC,CAAC,EAAE,CAAC,CAAC;IACN,CAAC,EAAE,EAAE,EAAE,CAAC;IACR,CAAC,CAAC,EAAE,CAAC,CAAC;IACN,CAAC,EAAE,EAAE,EAAE,CAAC;IACR,CAAC,CAAC,EAAE,CAAC,CAAC;IACN,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;IACT,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACP,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;IACT,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;IACV,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACR,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;IACV,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACP,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC;IACT,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACP,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC;CACV,CAAC;AACF,MAAM,UAAU,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAC5C,kFAAkF;AAClF,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAC7B,yFAAyF;AACzF,MAAM,YAAY,GAAG,EAAE,CAAC;AAExB,MAAM,QAAQ,GAAG,CAAC,EAAU,EAAE,EAAU,EAAE,EAAU,EAAE,EAAU,EAAU,EAAE,CAC1E,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;AAE3D;;;GAGG;AACH,SAAS,MAAM,CACb,KAAyB,EACzB,KAAqB,EACrB,OAAe,EACf,CAAS,EACT,EAAU,EACV,EAAU,EACV,MAAc;IAEd,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,KAAK,CAAC;IAC7D,MAAM,GAAG,GAAc,EAAE,CAAC;IAC1B,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;QAC1B,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;QACtB,IAAI,CAAC,KAAK,CAAC;YAAE,SAAS;QACtB,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,MAAM,GAAG,EAAE,CAAC,CAAC,CAAE,GAAG,EAAE,CAAC,CAAC,CAAE,GAAG,OAAO;YAAE,SAAS;QAC1E,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAE,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAE,CAAC,CAAC;QAC5C,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,GAAG,EAAE,CAAC,CAAC,CAAE,GAAG,EAAE,CAAC,CAAC,CAAE,GAAG,OAAO;YAAE,SAAS;QAChE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;GAGG;AACH,SAAS,MAAM,CACb,MAA0B,EAC1B,KAAqB,EACrB,OAAe,EACf,CAAS,EACT,CAAS,EACT,CAAS,EACT,QAAiC;IAEjC,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,KAAK,CAAC;IAC7D,MAAM,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAE,CAAC;IACtB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;QACtB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YAAE,SAAS;QAClE,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAE,GAAG,EAAE,CAAC,CAAC,CAAE,GAAG,OAAO;YAAE,SAAS;QACjE,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAE,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAE,GAAG,EAAE,CAAC,CAAC,CAAE,GAAG,OAAO;YAAE,SAAS;QAC3E,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,YAAY,CAC1B,KAAyB,EACzB,OAA0B,EAC1B,KAAqB,EACrB,OAAe,EACf,WAAmB;IAEnB,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IACtE,MAAM,GAAG,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,EAAE,CAAC,CAAC,CAAE,GAAG,EAAE,CAAC,CAAC,CAAE,CAAC;IACnD,MAAM,MAAM,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,EAAE,CAAC,CAAC,CAAE,GAAG,EAAE,CAAC,CAAC,CAAE,CAAC;IACtD,MAAM,GAAG,GAAG,OAAO,GAAG,IAAI,CAAC;IAC3B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;IACjC,MAAM,SAAS,GAAG,CAAC,CAAS,EAAW,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAE5E,KAAK,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;QACxC,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;QACvB,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;QACxB,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,SAAS,IAAI,SAAS,CAAC,KAAK,CAAC;YAAE,SAAS;QACrE,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7C,IAAI,OAAO,IAAI,WAAW;YAAE,SAAS;QAErC,MAAM,MAAM,GAAG,CAAC,EAAE,CAAC,MAAM,CAAE,GAAG,EAAE,CAAC,KAAK,CAAE,GAAG,GAAG,CAAC,GAAG,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;QACrF,MAAM,MAAM,GACV,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC;YAC1E,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;QACrC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QACxF,IAAI,IAAyD,CAAC;QAC9D,IAAI,QAA6D,CAAC;QAClE,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;YAC9B,KAAK,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,UAAU,EAAE,CAAC;gBAClC,MAAM,EAAE,GACN,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAE,GAAG,EAAE,CAAC,KAAK,CAAE,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACxF,MAAM,EAAE,GACN,EAAE,KAAK,CAAC;oBACN,CAAC,CAAC,MAAM,CAAC,iBAAiB;oBAC1B,CAAC,CAAC,EAAE,GAAG,CAAC;wBACN,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE;wBAC1C,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;gBAClD,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC;gBAClC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;gBACvB,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;gBACvB,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC1C,IAAI,QAAQ,IAAI,OAAO;oBAAE,SAAS;gBAClC,MAAM,KAAK,GAAG,QAAQ,GAAG,GAAG,GAAG,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;gBACxD,IAAI,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;oBAChD,IAAI,IAAI,KAAK,SAAS,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI;wBAAE,IAAI,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC;gBAC9E,CAAC;qBAAM,IACL,CAAC,QAAQ,KAAK,SAAS,IAAI,KAAK,GAAG,QAAQ,CAAC,KAAK,GAAG,IAAI,CAAC;oBACzD,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC,EACtD,CAAC;oBACD,QAAQ,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC;gBAC7B,CAAC;YACH,CAAC;QACH,CAAC;QACD,oFAAoF;QACpF,MAAM,OAAO,GAAG,gBAAgB,GAAG,WAAW,CAAC;QAC/C,MAAM,IAAI,GACR,QAAQ,KAAK,SAAS,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,QAAQ,CAAC,KAAK,GAAG,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC;YACrF,CAAC,CAAC,QAAQ;YACV,CAAC,CAAC,IAAI,CAAC;QACX,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;YACb,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;YACb,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;YACT,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;YACT,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAClB,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAyB,EACzB,KAAqB,EACrB,OAAe,EACf,IAAmE;IAEnE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;QACrB,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;YAAE,SAAS;QAC/B,IACE,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,EAC9F,CAAC;YACD,SAAS;QACX,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACvB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAE,GAAG,OAAO,CAAC,CAAC;QAC5C,0EAA0E;QAC1E,IAAI,MAAM,GAAc,EAAE,CAAC;QAC3B,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,IAAI,YAAY,EAAE,IAAI,EAAE,EAAE,CAAC;YAChD,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,MAAM,GAAG,MAAM,CACb,KAAK,EACL,KAAK,EACL,OAAO,EACP,CAAC,EACD,MAAM,CAAC,CAAC,EACR,MAAM,CAAC,CAAC,EACR,IAAI,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAC/B,CAAC;YACJ,CAAC;YACD,IAAI,IAAqD,CAAC;YAC1D,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAE,CAAS,EAAQ,EAAE;gBAC9C,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;gBAC7C,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI;oBAAE,OAAO;gBACrD,IAAI,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;oBAAE,IAAI,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;YAClE,CAAC,CAAC;YACF,MAAM,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;YACtB,KAAK,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;gBACnC,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC5C,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC9C,CAAC;YACD,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;gBACrC,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;gBAC5C,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;YAC9C,CAAC;YACD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACvB,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;gBAChB,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;gBAChB,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}