@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
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 iiwish and kgdiff contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,47 @@
1
- # Temporary Holding Version
1
+ # @kgdiff/layout
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Stable, deterministic, label-aware layout for graph diffs. Both versions of a graph share one
4
+ set of coordinates, the union layout, so nothing jumps when a viewer switches between before,
5
+ after, overlay and replay: only what changed moves, and removed nodes stay where they were.
6
+
7
+ ## Install
8
+
9
+ ```sh
10
+ pnpm add @kgdiff/layout @kgdiff/core
11
+ ```
12
+
13
+ ESM only. Node.js ≥ 22 or any evergreen browser.
14
+
15
+ ## Quick start
16
+
17
+ ```ts
18
+ import { diff } from '@kgdiff/core';
19
+ import { layoutDiff, layoutToJSON } from '@kgdiff/layout';
20
+
21
+ const result = diff(before, after);
22
+ const layout = layoutDiff(result);
23
+
24
+ layout.positions.get('company'); // { x, y } in world units, keyed by union node id
25
+ layout.scope; // 'all', or 'changes' above 3000 nodes: the changes and their context only
26
+
27
+ // Same input and seed → identical output, so a layout can be cached or embedded in a report.
28
+ const json = JSON.stringify(layoutToJSON(layout));
29
+ ```
30
+
31
+ Options worth knowing:
32
+
33
+ - `scope` (`'all'` | `'changes'`), `contextHops` and `hubDegree` decide which nodes are placed.
34
+ - `strategy: 'anchored'` with `pinned` positions keeps an existing layout and places only new
35
+ nodes.
36
+ - `extendLayout(result, layout, ids)` adds nodes next to their neighbours without moving any node
37
+ already placed, e.g. when a user expands a collapsed group.
38
+
39
+ ## Learn more
40
+
41
+ - [Algorithms § Layout](../../docs/algorithms.md#12-layout-layoutdiff): the simulation, label
42
+ awareness, component packing and quality bars.
43
+ - [Architecture](../../docs/architecture.md): budgets and how the packages fit together.
44
+
45
+ ## License
46
+
47
+ [MIT](../../LICENSE)
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Connected components over links AND merge / split partners (a merge source with no edges of
3
+ * its own still belongs next to its target).
4
+ */
5
+ import type { LayoutGraph } from './graph.js';
6
+ /**
7
+ * Components as ascending index lists, largest first (ties: smallest first index, i.e. id order).
8
+ * `members` restricts the computation to a subset (others are ignored).
9
+ */
10
+ export declare function connectedComponents(graph: LayoutGraph, members?: Uint8Array): number[][];
11
+ //# sourceMappingURL=components.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../src/components.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAsB9C;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,MAAM,EAAE,EAAE,CAyBxF"}
@@ -0,0 +1,56 @@
1
+ function find(parent, i) {
2
+ let root = i;
3
+ while (parent[root] !== root)
4
+ root = parent[root];
5
+ let cur = i;
6
+ while (parent[cur] !== root) {
7
+ const next = parent[cur];
8
+ parent[cur] = root;
9
+ cur = next;
10
+ }
11
+ return root;
12
+ }
13
+ function union(parent, a, b) {
14
+ const ra = find(parent, a);
15
+ const rb = find(parent, b);
16
+ // Smaller index becomes the root: the result does not depend on edge order.
17
+ if (ra < rb)
18
+ parent[rb] = ra;
19
+ else if (rb < ra)
20
+ parent[ra] = rb;
21
+ }
22
+ /**
23
+ * Components as ascending index lists, largest first (ties: smallest first index, i.e. id order).
24
+ * `members` restricts the computation to a subset (others are ignored).
25
+ */
26
+ export function connectedComponents(graph, members) {
27
+ const { n } = graph;
28
+ const parent = new Int32Array(n);
29
+ for (let i = 0; i < n; i++)
30
+ parent[i] = i;
31
+ const inSet = (i) => members === undefined || members[i] === 1;
32
+ for (let k = 0; k < graph.pairs.length; k += 2) {
33
+ const a = graph.pairs[k];
34
+ const b = graph.pairs[k + 1];
35
+ if (inSet(a) && inSet(b))
36
+ union(parent, a, b);
37
+ }
38
+ for (const { mover, anchor } of graph.partners) {
39
+ if (inSet(mover) && inSet(anchor))
40
+ union(parent, mover, anchor);
41
+ }
42
+ const byRoot = new Map();
43
+ for (let i = 0; i < n; i++) {
44
+ if (!inSet(i))
45
+ continue;
46
+ const root = find(parent, i);
47
+ let list = byRoot.get(root);
48
+ if (list === undefined) {
49
+ list = [];
50
+ byRoot.set(root, list);
51
+ }
52
+ list.push(i);
53
+ }
54
+ return [...byRoot.values()].sort((a, b) => b.length - a.length || a[0] - b[0]);
55
+ }
56
+ //# sourceMappingURL=components.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.js","sourceRoot":"","sources":["../src/components.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { LayoutGraph } from './graph.js';
2
+ import { type ResolvedLayoutOptions } from './options.js';
3
+ export interface EngineContext {
4
+ readonly graph: LayoutGraph;
5
+ readonly options: ResolvedLayoutOptions;
6
+ /** Positions by layout index, filled in place. */
7
+ readonly x: Float64Array;
8
+ readonly y: Float64Array;
9
+ }
10
+ /**
11
+ * Lay out everything freely. Returns the ticks of the largest simulation run (0 when none ran,
12
+ * e.g. only isolated nodes).
13
+ */
14
+ export declare function placeFree(ctx: EngineContext): number;
15
+ /**
16
+ * Lay out around `fixed` nodes, whose positions must already be in `ctx.x` / `ctx.y`.
17
+ * Returns the ticks of the largest simulation run (0 when none ran).
18
+ */
19
+ export declare function placeAnchored(ctx: EngineContext, fixed: Uint8Array): number;
20
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,EAAqB,KAAK,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAc7E,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,qBAAqB,CAAC;IACxC,kDAAkD;IAClD,QAAQ,CAAC,CAAC,EAAE,YAAY,CAAC;IACzB,QAAQ,CAAC,CAAC,EAAE,YAAY,CAAC;CAC1B;AAmBD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAQpD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,UAAU,GAAG,MAAM,CAiE3E"}
package/dist/engine.js ADDED
@@ -0,0 +1,336 @@
1
+ /**
2
+ * Placement strategies over a `LayoutGraph` (docs/algorithms.md §12 "Strategy", "Components").
3
+ *
4
+ * - `placeFree`: every component laid out on its own, packed, centered at the origin.
5
+ * - `placeAnchored`: known nodes never move; unknown nodes connected to them are seeded next to
6
+ * their placed neighbours and refined by a simulation in which the known nodes are fixed;
7
+ * components without any known node are laid out freely and packed beside the anchored region.
8
+ */
9
+ import { quadtree } from 'd3-quadtree';
10
+ import { connectedComponents } from './components.js';
11
+ import { removeOverlaps } from './forces/collide-rect.js';
12
+ import { settleOverlapping } from './forces/free-spot.js';
13
+ import { anchoredChargeRange, CHARGE_RANGE, chargeStrength, gravityFor, linkDistance, linkStrength, } from './forces/params.js';
14
+ import { BOX_PADDING, extentOf, isEmpty } from './geometry.js';
15
+ import { partnerLists, placeAroundFixed, placeOnSpiral } from './init.js';
16
+ import { defaultIterations } from './options.js';
17
+ import { pack } from './pack.js';
18
+ import { mulberry32 } from './prng.js';
19
+ import { simulate } from './simulate.js';
20
+ /** Merge / split partner springs (docs/algorithms.md §12), rest length 0.5·L. */
21
+ const SPRING_STRENGTH = 0.08;
22
+ const SPRING_LENGTH_RATIO = 0.5;
23
+ /** Spiral spacing relative to the link distance: starts a bit denser than the final layout. */
24
+ const SPIRAL_SPACING_RATIO = 0.4;
25
+ const TARGET_ASPECT = 1.6;
26
+ /** Pushing passes before wedged nodes are moved to free spots instead. */
27
+ const SETTLE_PASSES = 24;
28
+ const workspace = (ctx) => ({
29
+ partners: partnerLists(ctx.graph),
30
+ slot: new Int32Array(ctx.graph.n).fill(-1),
31
+ random: mulberry32(ctx.options.seed),
32
+ });
33
+ /** Ticks for a simulation over `size` nodes: the option, else `defaultIterations(size)`. */
34
+ const ticksFor = (ctx, size) => ctx.options.iterations ?? defaultIterations(size);
35
+ /**
36
+ * Lay out everything freely. Returns the ticks of the largest simulation run (0 when none ran,
37
+ * e.g. only isolated nodes).
38
+ */
39
+ export function placeFree(ctx) {
40
+ const ws = workspace(ctx);
41
+ const components = connectedComponents(ctx.graph);
42
+ const block = layoutBlock(ctx, ws, components);
43
+ const all = components.flat();
44
+ const e = extentOf(ctx.graph, all, ctx.x, ctx.y);
45
+ if (!isEmpty(e))
46
+ translate(ctx, all, -(e.minX + e.maxX) / 2, -(e.minY + e.maxY) / 2);
47
+ return block.ticks;
48
+ }
49
+ /**
50
+ * Lay out around `fixed` nodes, whose positions must already be in `ctx.x` / `ctx.y`.
51
+ * Returns the ticks of the largest simulation run (0 when none ran).
52
+ */
53
+ export function placeAnchored(ctx, fixed) {
54
+ const { graph } = ctx;
55
+ const ws = workspace(ctx);
56
+ const components = connectedComponents(graph);
57
+ const anchoredComponents = [];
58
+ const freeComponents = [];
59
+ for (const component of components) {
60
+ (component.some((i) => fixed[i] === 1) ? anchoredComponents : freeComponents).push(component);
61
+ }
62
+ const members = anchoredComponents.flat().sort((a, b) => a - b);
63
+ const placed = Uint8Array.from(fixed);
64
+ placeAroundFixed(graph, ws.partners, members, placed, ctx.x, ctx.y, ctx.options.linkDistance, ctx.options.seed);
65
+ const free = members.filter((i) => fixed[i] !== 1);
66
+ let ticks = 0;
67
+ let largest = 0;
68
+ if (free.length > 0) {
69
+ // Refine with an energy (and a charge range) matching how much of the picture is new.
70
+ const share = free.length / members.length;
71
+ const window = simulationWindow(ctx, members, free, fixed);
72
+ ticks = ticksFor(ctx, window.length);
73
+ largest = window.length;
74
+ runSimulation(ctx, ws, window, fixed, ticks, 0.3 + 0.7 * share, false, 0, anchoredChargeRange(share, ctx.options.linkDistance));
75
+ settle(ctx, members, fixed);
76
+ }
77
+ if (freeComponents.length > 0) {
78
+ const block = layoutBlock(ctx, ws, freeComponents);
79
+ if (block.largest > largest)
80
+ ticks = block.ticks;
81
+ const anchoredExtent = extentOf(graph, members, ctx.x, ctx.y);
82
+ const nodes = freeComponents.flat();
83
+ const gap = ctx.options.componentGap;
84
+ const right = { dx: anchoredExtent.maxX + gap, dy: anchoredExtent.minY };
85
+ const below = { dx: anchoredExtent.minX, dy: anchoredExtent.maxY + gap };
86
+ const cost = (dx, dy) => {
87
+ const w = Math.max(anchoredExtent.maxX, dx + block.width) - Math.min(anchoredExtent.minX, dx);
88
+ const h = Math.max(anchoredExtent.maxY, dy + block.height) - Math.min(anchoredExtent.minY, dy);
89
+ const side = Math.max(w, h * TARGET_ASPECT);
90
+ return side * side;
91
+ };
92
+ const at = cost(below.dx, below.dy) < cost(right.dx, right.dy) - 1e-6 ? below : right;
93
+ translate(ctx, nodes, at.dx, at.dy);
94
+ }
95
+ return ticks;
96
+ }
97
+ /**
98
+ * The nodes worth simulating around `free` ones: all of them, their graph neighbours, and the
99
+ * fixed nodes within reach of where any of them starts (a quadtree range query per free node).
100
+ * Far-away fixed nodes cannot interact with the new ones in a refinement run, and skipping them
101
+ * keeps `extendLayout` interactive on large graphs.
102
+ */
103
+ function simulationWindow(ctx, members, free, fixed) {
104
+ const { graph, x, y } = ctx;
105
+ if (free.length * 2 >= members.length)
106
+ return [...members];
107
+ const inWindow = new Uint8Array(graph.n);
108
+ let reach = 4 * ctx.options.linkDistance;
109
+ for (const i of free) {
110
+ reach = Math.max(reach, 2 * graph.boxHalfWidth[i], 2 * graph.boxBottom[i]);
111
+ inWindow[i] = 1;
112
+ for (let k = graph.offsets[i]; k < graph.offsets[i + 1]; k++)
113
+ inWindow[graph.adjacency[k]] = 1;
114
+ }
115
+ const tree = quadtree()
116
+ .x((i) => x[i])
117
+ .y((i) => y[i])
118
+ .addAll(members.filter((i) => fixed[i] === 1));
119
+ for (const i of free) {
120
+ const x0 = x[i] - reach;
121
+ const x1 = x[i] + reach;
122
+ const y0 = y[i] - reach;
123
+ const y1 = y[i] + reach;
124
+ tree.visit((cell, cx0, cy0, cx1, cy1) => {
125
+ if (!cell.length) {
126
+ let leaf = cell;
127
+ while (leaf !== undefined) {
128
+ const j = leaf.data;
129
+ if (x[j] >= x0 && x[j] <= x1 && y[j] >= y0 && y[j] <= y1)
130
+ inWindow[j] = 1;
131
+ leaf = leaf.next;
132
+ }
133
+ }
134
+ return cx0 > x1 || cx1 < x0 || cy0 > y1 || cy1 < y0;
135
+ });
136
+ }
137
+ return members.filter((i) => inWindow[i] === 1);
138
+ }
139
+ /**
140
+ * Simulate each multi-node component around the origin, then pack all of them (and the
141
+ * isolated nodes) into one block whose visual extent starts at (0, 0).
142
+ */
143
+ function layoutBlock(ctx, ws, components) {
144
+ const { graph, x, y, options } = ctx;
145
+ const visited = new Uint8Array(graph.n);
146
+ const groups = [];
147
+ const isolated = [];
148
+ const extents = [];
149
+ let ticks = 0;
150
+ let largest = 0;
151
+ for (const component of components) {
152
+ if (component.length === 1) {
153
+ isolated.push(component[0]);
154
+ continue;
155
+ }
156
+ placeOnSpiral(graph, ws.partners, component, options.linkDistance * SPIRAL_SPACING_RATIO, ws.random, visited, x, y);
157
+ const componentTicks = ticksFor(ctx, component.length);
158
+ // Components come largest first.
159
+ if (component.length > largest) {
160
+ largest = component.length;
161
+ ticks = componentTicks;
162
+ }
163
+ runSimulation(ctx, ws, component, undefined, componentTicks, 1, true, gravityFor(component.length), CHARGE_RANGE);
164
+ groups.push(component);
165
+ extents.push(extentOf(graph, component, x, y));
166
+ }
167
+ isolated.sort((a, b) => a - b);
168
+ const packed = pack({
169
+ components: extents.map((e) => ({ width: e.maxX - e.minX, height: e.maxY - e.minY })),
170
+ isolated: isolated.map((i) => ({
171
+ halfWidth: graph.boxHalfWidth[i],
172
+ top: graph.boxTop[i],
173
+ bottom: graph.boxBottom[i],
174
+ })),
175
+ componentGap: options.componentGap,
176
+ gridGapX: options.fontSize * 1.5,
177
+ gridGapY: options.fontSize,
178
+ aspect: TARGET_ASPECT,
179
+ });
180
+ for (let c = 0; c < groups.length; c++) {
181
+ const at = packed.components[c];
182
+ const e = extents[c];
183
+ translate(ctx, groups[c], at.x - e.minX, at.y - e.minY);
184
+ }
185
+ for (let k = 0; k < isolated.length; k++) {
186
+ const i = isolated[k];
187
+ const at = packed.isolated[k];
188
+ x[i] = at.x;
189
+ y[i] = at.y;
190
+ }
191
+ return { width: packed.width, height: packed.height, ticks, largest };
192
+ }
193
+ function translate(ctx, nodes, dx, dy) {
194
+ for (const i of nodes) {
195
+ ctx.x[i] += dx;
196
+ ctx.y[i] += dy;
197
+ }
198
+ }
199
+ /** Sim nodes (index k ↔ `list[k]`), collision boxes and charges for a list of layout indices. */
200
+ function setup(ctx, list, fixed) {
201
+ const { graph, x, y, options } = ctx;
202
+ const m = list.length;
203
+ const nodeBoxes = {
204
+ halfWidth: new Float64Array(m),
205
+ halfHeight: new Float64Array(m),
206
+ offsetY: new Float64Array(m),
207
+ invMass: new Float64Array(m),
208
+ };
209
+ const labelBoxes = options.labelAware
210
+ ? {
211
+ halfWidth: new Float64Array(m),
212
+ halfHeight: new Float64Array(m),
213
+ offsetY: new Float64Array(m),
214
+ invMass: nodeBoxes.invMass,
215
+ }
216
+ : nodeBoxes;
217
+ const charge = new Float64Array(m);
218
+ const nodes = [];
219
+ for (let k = 0; k < m; k++) {
220
+ const i = list[k];
221
+ const r = graph.radius[i];
222
+ const isFixed = fixed !== undefined && fixed[i] === 1;
223
+ const node = { index: k, x: x[i], y: y[i], vx: 0, vy: 0 };
224
+ if (isFixed) {
225
+ node.fx = node.x;
226
+ node.fy = node.y;
227
+ }
228
+ nodes.push(node);
229
+ nodeBoxes.halfWidth[k] = r;
230
+ nodeBoxes.halfHeight[k] = r;
231
+ // Hubs are heavy: in a collision the leaf steps aside. Fixed nodes never move.
232
+ nodeBoxes.invMass[k] = isFixed ? 0 : 1 / (1 + graph.degree[i]);
233
+ if (labelBoxes !== nodeBoxes) {
234
+ labelBoxes.halfWidth[k] = graph.boxHalfWidth[i];
235
+ labelBoxes.halfHeight[k] = (graph.boxBottom[i] - graph.boxTop[i]) / 2;
236
+ labelBoxes.offsetY[k] = (graph.boxBottom[i] + graph.boxTop[i]) / 2;
237
+ }
238
+ charge[k] = chargeStrength(graph, i, options.linkDistance, options.labelAware);
239
+ }
240
+ return { nodes, nodeBoxes, labelBoxes, charge };
241
+ }
242
+ function writeBack(ctx, list, nodes) {
243
+ for (let k = 0; k < list.length; k++) {
244
+ const node = nodes[k];
245
+ if (node.fx == null) {
246
+ ctx.x[list[k]] = node.x;
247
+ ctx.y[list[k]] = node.y;
248
+ }
249
+ }
250
+ }
251
+ /** Simulate `list` (ascending layout indices) in place; fixed nodes keep their position. */
252
+ function runSimulation(ctx, ws, list, fixed, ticks, alpha, orient, gravity, chargeRange) {
253
+ const { graph, options } = ctx;
254
+ const { slot } = ws;
255
+ for (let k = 0; k < list.length; k++)
256
+ slot[list[k]] = k;
257
+ const { nodes, nodeBoxes, labelBoxes, charge } = setup(ctx, list, fixed);
258
+ const isFixed = (i) => fixed !== undefined && fixed[i] === 1;
259
+ const L = options.linkDistance;
260
+ const links = [];
261
+ for (let k = 0; k < list.length; k++) {
262
+ const i = list[k];
263
+ for (let e = graph.offsets[i]; e < graph.offsets[i + 1]; e++) {
264
+ const v = graph.adjacency[e];
265
+ const kv = slot[v];
266
+ if (v <= i || kv < 0 || (isFixed(i) && isFixed(v)))
267
+ continue;
268
+ const distance = linkDistance(L, Math.max(1, Math.min(graph.degree[i], graph.degree[v])));
269
+ links.push({
270
+ source: nodes[k],
271
+ target: nodes[kv],
272
+ distance,
273
+ strength: linkStrength(graph, i, v, distance, options.labelAware),
274
+ });
275
+ }
276
+ }
277
+ const springs = [];
278
+ for (const { mover, anchor } of graph.partners) {
279
+ const km = slot[mover];
280
+ const ka = slot[anchor];
281
+ if (km >= 0 && ka >= 0)
282
+ springs.push({ mover: km, anchor: ka });
283
+ }
284
+ for (const i of list)
285
+ slot[i] = -1;
286
+ simulate({
287
+ nodes,
288
+ links,
289
+ springs,
290
+ charge,
291
+ nodeBoxes,
292
+ labelBoxes,
293
+ ticks,
294
+ alpha,
295
+ gravity,
296
+ orient,
297
+ springStrength: SPRING_STRENGTH,
298
+ springLength: L * SPRING_LENGTH_RATIO,
299
+ dockDistance: L,
300
+ chargeRange,
301
+ padding: BOX_PADDING,
302
+ random: ws.random,
303
+ });
304
+ writeBack(ctx, list, nodes);
305
+ }
306
+ /**
307
+ * Final overlap removal over the whole anchored region (`list`), fixed nodes being immovable
308
+ * obstacles: pushes first (new nodes may have drifted next to fixed nodes outside the simulation
309
+ * window), then free spots for nodes that pushing cannot free.
310
+ */
311
+ function settle(ctx, list, fixed) {
312
+ const { graph, x, y } = ctx;
313
+ const { nodes, labelBoxes } = setup(ctx, list, fixed);
314
+ removeOverlaps(nodes, labelBoxes, BOX_PADDING, SETTLE_PASSES);
315
+ const slotOf = new Map();
316
+ list.forEach((i, k) => {
317
+ slotOf.set(i, k);
318
+ });
319
+ settleOverlapping(nodes, labelBoxes, BOX_PADDING, (k) => {
320
+ const i = list[k];
321
+ let sx = 0;
322
+ let sy = 0;
323
+ let count = 0;
324
+ for (let e = graph.offsets[i]; e < graph.offsets[i + 1]; e++) {
325
+ const node = nodes[slotOf.get(graph.adjacency[e]) ?? -1];
326
+ if (node === undefined)
327
+ continue;
328
+ sx += node.x;
329
+ sy += node.y;
330
+ count++;
331
+ }
332
+ return count > 0 ? { x: sx / count, y: sy / count } : { x: x[i], y: y[i] };
333
+ });
334
+ writeBack(ctx, list, nodes);
335
+ }
336
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * `extendLayout`: add nodes to an existing layout without moving anything already placed.
3
+ */
4
+ import { type DiffResult, type UnionId } from '@kgdiff/core';
5
+ import type { LayoutOptions, LayoutResult } from './index.js';
6
+ export declare function extend(diff: DiffResult, layout: LayoutResult, nodes: readonly UnionId[], options: LayoutOptions | undefined, nodeRadius: (degree: number) => number): LayoutResult;
7
+ //# sourceMappingURL=extend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extend.d.ts","sourceRoot":"","sources":["../src/extend.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,KAAK,UAAU,EAA2B,KAAK,OAAO,EAAE,MAAM,cAAc,CAAC;AAGtF,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAO9D,wBAAgB,MAAM,CACpB,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,SAAS,OAAO,EAAE,EACzB,OAAO,EAAE,aAAa,GAAG,SAAS,EAClC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,GACrC,YAAY,CAuDd"}
package/dist/extend.js ADDED
@@ -0,0 +1,68 @@
1
+ /**
2
+ * `extendLayout`: add nodes to an existing layout without moving anything already placed.
3
+ */
4
+ import { KgdiffError } from '@kgdiff/core';
5
+ import { placeAnchored } from './engine.js';
6
+ import { buildLayoutGraph } from './graph.js';
7
+ import { round2 } from './math.js';
8
+ import { resolveLayoutOptions } from './options.js';
9
+ import { assemble, now } from './result.js';
10
+ import { countHidden } from './scope.js';
11
+ import { buildUnionGraph } from './union.js';
12
+ export function extend(diff, layout, nodes, options, nodeRadius) {
13
+ const started = now();
14
+ const opts = resolveLayoutOptions(options);
15
+ const union = buildUnionGraph(diff);
16
+ const added = new Set();
17
+ for (const id of nodes) {
18
+ if (!union.indexOf.has(id)) {
19
+ throw new KgdiffError('invalid-input', `extendLayout: node "${id}" is not in the diff`, {
20
+ node: id,
21
+ });
22
+ }
23
+ if (!layout.positions.has(id))
24
+ added.add(id);
25
+ }
26
+ if (added.size === 0)
27
+ return layout;
28
+ const visible = new Uint8Array(union.nodes.length);
29
+ for (const id of layout.positions.keys()) {
30
+ const u = union.indexOf.get(id);
31
+ if (u !== undefined)
32
+ visible[u] = 1;
33
+ }
34
+ for (const id of added)
35
+ visible[union.indexOf.get(id)] = 1;
36
+ const graph = buildLayoutGraph(union, visible, { fontSize: opts.fontSize, nodeRadius });
37
+ const fixed = new Uint8Array(graph.n);
38
+ const x = new Float64Array(graph.n);
39
+ const y = new Float64Array(graph.n);
40
+ for (let i = 0; i < graph.n; i++) {
41
+ const p = layout.positions.get(graph.nodes[i].id);
42
+ if (p === undefined)
43
+ continue;
44
+ fixed[i] = 1;
45
+ x[i] = p.x;
46
+ y[i] = p.y;
47
+ }
48
+ const ctx = { graph, options: opts, x, y };
49
+ placeAnchored(ctx, fixed);
50
+ const positions = new Map(layout.positions);
51
+ const radii = new Map(layout.radii);
52
+ for (const id of added) {
53
+ const i = graph.indexOf.get(id);
54
+ positions.set(id, Object.freeze({ x: round2(x[i]), y: round2(y[i]) }));
55
+ radii.set(id, graph.radius[i]);
56
+ }
57
+ return assemble({
58
+ graph,
59
+ positions,
60
+ radii,
61
+ hidden: layout.scope === 'changes' ? countHidden(union, visible) : layout.hidden,
62
+ scope: layout.scope,
63
+ strategy: layout.stats.strategy,
64
+ iterations: layout.stats.iterations,
65
+ started,
66
+ });
67
+ }
68
+ //# sourceMappingURL=extend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extend.js","sourceRoot":"","sources":["../src/extend.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAmB,WAAW,EAA4B,MAAM,cAAc,CAAC;AACtF,OAAO,EAAsB,aAAa,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,UAAU,MAAM,CACpB,IAAgB,EAChB,MAAoB,EACpB,KAAyB,EACzB,OAAkC,EAClC,UAAsC;IAEtC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC;IACtB,MAAM,IAAI,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IAEpC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAW,CAAC;IACjC,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC;QACvB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,WAAW,CAAC,eAAe,EAAE,uBAAuB,EAAE,sBAAsB,EAAE;gBACtF,IAAI,EAAE,EAAE;aACT,CAAC,CAAC;QACL,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC/C,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IAEpC,MAAM,OAAO,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACnD,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;QACzC,MAAM,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK,SAAS;YAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACtC,CAAC;IACD,KAAK,MAAM,EAAE,IAAI,KAAK;QAAE,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAE,CAAC,GAAG,CAAC,CAAC;IAC5D,MAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC;IAExF,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,CAAC,GAAG,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACpC,MAAM,CAAC,GAAG,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACjC,MAAM,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC,CAAC;QACnD,IAAI,CAAC,KAAK,SAAS;YAAE,SAAS;QAC9B,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACb,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACX,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACb,CAAC;IACD,MAAM,GAAG,GAAkB,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;IAC1D,aAAa,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAE1B,MAAM,SAAS,GAAG,IAAI,GAAG,CAAiB,MAAM,CAAC,SAAS,CAAC,CAAC;IAC5D,MAAM,KAAK,GAAG,IAAI,GAAG,CAAkB,MAAM,CAAC,KAAK,CAAC,CAAC;IACrD,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC;QACvB,MAAM,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAE,CAAC;QACjC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACzE,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,QAAQ,CAAC;QACd,KAAK;QACL,SAAS;QACT,KAAK;QACL,MAAM,EAAE,MAAM,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM;QAChF,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,QAAQ;QAC/B,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC,UAAU;QACnC,OAAO;KACR,CAAC,CAAC;AACL,CAAC"}