@coldtea/pr-lens-renderer 0.3.5 → 0.4.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.
- package/dist/atlas.d.ts +2 -0
- package/dist/atlas.d.ts.map +1 -1
- package/dist/atlas.js +1 -1
- package/dist/atlas.js.map +1 -1
- package/dist/corrections.d.ts.map +1 -1
- package/dist/corrections.js +7 -1
- package/dist/corrections.js.map +1 -1
- package/dist/design.d.ts +25 -0
- package/dist/design.d.ts.map +1 -1
- package/dist/design.js +25 -0
- package/dist/design.js.map +1 -1
- package/dist/layout/architecture.d.ts +6 -2
- package/dist/layout/architecture.d.ts.map +1 -1
- package/dist/layout/architecture.js +12 -19
- package/dist/layout/architecture.js.map +1 -1
- package/dist/layout/datamodel.d.ts +70 -0
- package/dist/layout/datamodel.d.ts.map +1 -0
- package/dist/layout/datamodel.js +381 -0
- package/dist/layout/datamodel.js.map +1 -0
- package/dist/layout/edges.d.ts +8 -0
- package/dist/layout/edges.d.ts.map +1 -1
- package/dist/layout/edges.js +2 -2
- package/dist/layout/edges.js.map +1 -1
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +18 -1
- package/dist/render.js.map +1 -1
- package/dist/scope.d.ts +4 -1
- package/dist/scope.d.ts.map +1 -1
- package/dist/scope.js +28 -2
- package/dist/scope.js.map +1 -1
- package/dist/svg/architecture.d.ts +5 -2
- package/dist/svg/architecture.d.ts.map +1 -1
- package/dist/svg/architecture.js +10 -11
- package/dist/svg/architecture.js.map +1 -1
- package/dist/svg/datamodel.d.ts +11 -0
- package/dist/svg/datamodel.d.ts.map +1 -0
- package/dist/svg/datamodel.js +252 -0
- package/dist/svg/datamodel.js.map +1 -0
- package/dist/svg/icons.d.ts +2 -0
- package/dist/svg/icons.d.ts.map +1 -1
- package/dist/svg/icons.js +14 -0
- package/dist/svg/icons.js.map +1 -1
- package/dist/svg/styles.d.ts +3 -1
- package/dist/svg/styles.d.ts.map +1 -1
- package/dist/svg/styles.js +6 -0
- package/dist/svg/styles.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
- package/src/atlas.ts +3 -1
- package/src/corrections.ts +7 -1
- package/src/design.ts +26 -0
- package/src/layout/architecture.ts +16 -10
- package/src/layout/datamodel.ts +524 -0
- package/src/layout/edges.ts +2 -2
- package/src/render.ts +18 -1
- package/src/scope.ts +46 -3
- package/src/svg/architecture.ts +12 -13
- package/src/svg/datamodel.ts +344 -0
- package/src/svg/icons.ts +20 -0
- package/src/svg/styles.ts +8 -1
- package/src/version.ts +1 -1
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
import { CARD_HEIGHT_WITH_SUBTITLE, CONTENT_TOP, DIAGRAM_MARGIN, ICON_MIN_CARD_WIDTH, LANE_BOTTOM_PADDING, LANE_CONTENT_WIDTH, LANE_GAP, LANE_PADDING_X, LANE_TOP, OVER_CLEARANCE, OVER_PITCH, PILL_CARD_CLEARANCE, PORT_FAN_MAX, ROW_GAP, TABLE_FOLD_GAP, TABLE_FOLD_HEIGHT, TABLE_FOLD_MIN_HIDDEN, TABLE_ROW_HEIGHT, TABLE_ROWS_MAX, TABLE_ROWS_PADDING_Y, TABLE_UNCHANGED_ROWS_MAX, TITLE_SIZE, TITLE_SIZE_SMALL, TRACK_CLEARANCE, TRACK_PITCH_MAX, TRACK_PITCH_MIN, } from "../design.js";
|
|
2
|
+
import { curveThrough, pathOf } from "./edges.js";
|
|
3
|
+
import { pillSize } from "./labels.js";
|
|
4
|
+
/**
|
|
5
|
+
* Which columns a card draws. A key, a changed column, and the end of a key
|
|
6
|
+
* in scope are the reason the table is in the picture, so they stay; the
|
|
7
|
+
* unchanged rest is sampled up to a few; and the card never passes the
|
|
8
|
+
* ceiling. What is left out is counted, never silently dropped: the fold row
|
|
9
|
+
* says so, and the subtitle keeps the true count.
|
|
10
|
+
*/
|
|
11
|
+
export const foldColumns = (table, relations) => {
|
|
12
|
+
const ends = new Set(relations.flatMap(({ from, to }) => [from, to]).filter((end) => end.table === table.id).map((end) => end.column));
|
|
13
|
+
const tier = (column) => column.key !== undefined || ends.has(column.name) ? 0 : column.delta !== "unchanged" ? 1 : 2;
|
|
14
|
+
const keep = new Set();
|
|
15
|
+
let unchanged = 0;
|
|
16
|
+
for (const wanted of [0, 1, 2])
|
|
17
|
+
for (const column of table.columns) {
|
|
18
|
+
if (keep.size >= TABLE_ROWS_MAX)
|
|
19
|
+
break;
|
|
20
|
+
if (tier(column) !== wanted)
|
|
21
|
+
continue;
|
|
22
|
+
if (wanted === 2 && unchanged >= TABLE_UNCHANGED_ROWS_MAX)
|
|
23
|
+
break;
|
|
24
|
+
if (wanted === 2)
|
|
25
|
+
unchanged += 1;
|
|
26
|
+
keep.add(column);
|
|
27
|
+
}
|
|
28
|
+
const hidden = table.columns.length - keep.size;
|
|
29
|
+
if (hidden < TABLE_FOLD_MIN_HIDDEN)
|
|
30
|
+
return { shown: [...table.columns], hidden: 0, unchangedOnly: true };
|
|
31
|
+
return {
|
|
32
|
+
shown: table.columns.filter((column) => keep.has(column)),
|
|
33
|
+
hidden,
|
|
34
|
+
unchangedOnly: table.columns.every((column) => keep.has(column) || column.delta === "unchanged"),
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
export const tableHeight = (fold) => CARD_HEIGHT_WITH_SUBTITLE +
|
|
38
|
+
TABLE_ROWS_PADDING_Y * 2 +
|
|
39
|
+
fold.shown.length * TABLE_ROW_HEIGHT +
|
|
40
|
+
(fold.hidden > 0 ? TABLE_FOLD_HEIGHT : 0);
|
|
41
|
+
/**
|
|
42
|
+
* Lane order. A document that sets `order` on any store is honoured exactly:
|
|
43
|
+
* that is the author's intent, and a rename must never slide a lane. With no
|
|
44
|
+
* order given, the store most keys point into goes in the middle, so the
|
|
45
|
+
* routes reach it from both sides instead of all climbing over the top, and
|
|
46
|
+
* the rest keep their written order around it.
|
|
47
|
+
*/
|
|
48
|
+
const orderStores = (graph) => {
|
|
49
|
+
const { stores } = graph;
|
|
50
|
+
if (stores.some((store) => store.order !== undefined))
|
|
51
|
+
return stores
|
|
52
|
+
.map((store, index) => ({ store, index }))
|
|
53
|
+
.sort((a, b) => (a.store.order ?? Number.MAX_SAFE_INTEGER) - (b.store.order ?? Number.MAX_SAFE_INTEGER) ||
|
|
54
|
+
a.index - b.index)
|
|
55
|
+
.map(({ store }) => store);
|
|
56
|
+
const storeOf = new Map(graph.tables.map((table) => [table.id, table.store]));
|
|
57
|
+
const incoming = new Map();
|
|
58
|
+
for (const { from, to } of graph.relations) {
|
|
59
|
+
const target = storeOf.get(to.table);
|
|
60
|
+
if (target === undefined || target === storeOf.get(from.table))
|
|
61
|
+
continue;
|
|
62
|
+
incoming.set(target, (incoming.get(target) ?? 0) + 1);
|
|
63
|
+
}
|
|
64
|
+
const hub = stores.reduce((best, store) => (best === undefined || (incoming.get(store.id) ?? 0) > (incoming.get(best.id) ?? 0) ? store : best), undefined);
|
|
65
|
+
if (hub === undefined || (incoming.get(hub.id) ?? 0) === 0)
|
|
66
|
+
return [...stores];
|
|
67
|
+
const rest = stores.filter((store) => store !== hub);
|
|
68
|
+
const middle = Math.floor((stores.length - 1) / 2);
|
|
69
|
+
return [...rest.slice(0, middle), hub, ...rest.slice(middle)];
|
|
70
|
+
};
|
|
71
|
+
const laneOf = (tables, stores) => {
|
|
72
|
+
const index = new Map(stores.map((store, at) => [store.id, at]));
|
|
73
|
+
return new Map(tables.map((table) => [table.id, index.get(table.store) ?? 0]));
|
|
74
|
+
};
|
|
75
|
+
const GUTTER = LANE_PADDING_X * 2 + LANE_GAP;
|
|
76
|
+
/**
|
|
77
|
+
* Several keys landing on one column from one side merge their last leg into
|
|
78
|
+
* a trunk: one track in the corridor beside the target, one arrowhead on the
|
|
79
|
+
* port. Up to three arrivals still read as separate heads fanned a few pixels
|
|
80
|
+
* apart; from four the heads wedge, so four is where a trunk starts. Tones
|
|
81
|
+
* never merge: a new key and an unchanged one on the same port are two trunks.
|
|
82
|
+
*/
|
|
83
|
+
const TRUNK_MIN = 4;
|
|
84
|
+
const trunkKey = (relation, toSide) => `${relation.to.table}\u0000${relation.to.column}\u0000${toSide}\u0000${relation.delta}`;
|
|
85
|
+
/**
|
|
86
|
+
* What the routes ask of the gaps before anything is placed: how many cross
|
|
87
|
+
* above the lanes, and how many legs each corridor carries. Both follow from
|
|
88
|
+
* lane indices alone, so the lanes can be placed around them. A trunk counts
|
|
89
|
+
* once in the corridor it gathers in.
|
|
90
|
+
*/
|
|
91
|
+
const traffic = (graph, lanes, last) => {
|
|
92
|
+
const planned = graph.relations.map((relation) => ({
|
|
93
|
+
relation,
|
|
94
|
+
lanes: planLanes(lanes.get(relation.from.table) ?? 0, lanes.get(relation.to.table) ?? 0, last, relation.label),
|
|
95
|
+
}));
|
|
96
|
+
const trunkSizes = new Map();
|
|
97
|
+
for (const { relation, lanes: route } of planned) {
|
|
98
|
+
const key = trunkKey(relation, route.toSide);
|
|
99
|
+
trunkSizes.set(key, (trunkSizes.get(key) ?? 0) + 1);
|
|
100
|
+
}
|
|
101
|
+
const legs = new Map();
|
|
102
|
+
const counted = new Set();
|
|
103
|
+
let skips = 0;
|
|
104
|
+
for (const { relation, lanes: route } of planned) {
|
|
105
|
+
if (route.over)
|
|
106
|
+
skips += 1;
|
|
107
|
+
const key = trunkKey(relation, route.toSide);
|
|
108
|
+
const trunked = (trunkSizes.get(key) ?? 0) >= TRUNK_MIN;
|
|
109
|
+
route.corridors.forEach((corridor, index) => {
|
|
110
|
+
if (trunked && index === route.corridors.length - 1) {
|
|
111
|
+
if (counted.has(key))
|
|
112
|
+
return;
|
|
113
|
+
counted.add(key);
|
|
114
|
+
}
|
|
115
|
+
legs.set(corridor, (legs.get(corridor) ?? 0) + 1);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return { skips, legs };
|
|
119
|
+
};
|
|
120
|
+
/** Room a corridor needs beyond the gutter to hold its legs at the floor pitch. */
|
|
121
|
+
const corridorExtra = (legs) => Math.max(0, TRACK_CLEARANCE * 2 + TRACK_PITCH_MIN * (legs - 1) - GUTTER);
|
|
122
|
+
export const layoutDataModel = (graph) => {
|
|
123
|
+
const stores = orderStores(graph);
|
|
124
|
+
const lanes = laneOf(graph.tables, stores);
|
|
125
|
+
const { skips, legs } = traffic(graph, lanes, stores.length - 1);
|
|
126
|
+
const overBand = skips === 0 ? 0 : skips * OVER_PITCH + OVER_CLEARANCE;
|
|
127
|
+
const laneTop = LANE_TOP + overBand;
|
|
128
|
+
const contentTop = CONTENT_TOP + overBand;
|
|
129
|
+
const laneBoxWidth = LANE_CONTENT_WIDTH + LANE_PADDING_X * 2;
|
|
130
|
+
const extra = (corridor) => corridorExtra(legs.get(corridor) ?? 0);
|
|
131
|
+
// Lane `i` starts after corridor `i`, and a corridor fuller than the gutter holds pushes it along.
|
|
132
|
+
const laneLefts = [];
|
|
133
|
+
let laneX = DIAGRAM_MARGIN;
|
|
134
|
+
stores.forEach((_, laneIndex) => {
|
|
135
|
+
laneX += extra(laneIndex);
|
|
136
|
+
laneLefts.push(laneX);
|
|
137
|
+
laneX += laneBoxWidth + LANE_GAP;
|
|
138
|
+
});
|
|
139
|
+
const contentRight = laneX - LANE_GAP + extra(stores.length);
|
|
140
|
+
const tables = [];
|
|
141
|
+
let laneBottom = contentTop;
|
|
142
|
+
stores.forEach((store, laneIndex) => {
|
|
143
|
+
const x = (laneLefts[laneIndex] ?? DIAGRAM_MARGIN) + LANE_PADDING_X;
|
|
144
|
+
let y = contentTop;
|
|
145
|
+
for (const table of graph.tables) {
|
|
146
|
+
if (table.store !== store.id)
|
|
147
|
+
continue;
|
|
148
|
+
const fold = foldColumns(table, graph.relations);
|
|
149
|
+
const box = { x, y, width: LANE_CONTENT_WIDTH, height: tableHeight(fold) };
|
|
150
|
+
const rowsTop = y + CARD_HEIGHT_WITH_SUBTITLE + TABLE_ROWS_PADDING_Y;
|
|
151
|
+
const foldTop = rowsTop + fold.shown.length * TABLE_ROW_HEIGHT + TABLE_FOLD_GAP;
|
|
152
|
+
tables.push({
|
|
153
|
+
table,
|
|
154
|
+
box,
|
|
155
|
+
titleSize: LANE_CONTENT_WIDTH >= ICON_MIN_CARD_WIDTH ? TITLE_SIZE : TITLE_SIZE_SMALL,
|
|
156
|
+
columns: fold.shown.map((column, index) => ({
|
|
157
|
+
column,
|
|
158
|
+
top: rowsTop + index * TABLE_ROW_HEIGHT,
|
|
159
|
+
centre: rowsTop + index * TABLE_ROW_HEIGHT + TABLE_ROW_HEIGHT / 2,
|
|
160
|
+
})),
|
|
161
|
+
fold: fold.hidden === 0
|
|
162
|
+
? undefined
|
|
163
|
+
: { hidden: fold.hidden, unchangedOnly: fold.unchangedOnly, top: foldTop, centre: foldTop + TABLE_ROW_HEIGHT / 2 },
|
|
164
|
+
laneIndex,
|
|
165
|
+
});
|
|
166
|
+
y += box.height + ROW_GAP;
|
|
167
|
+
}
|
|
168
|
+
laneBottom = Math.max(laneBottom, y - ROW_GAP);
|
|
169
|
+
});
|
|
170
|
+
laneBottom += LANE_BOTTOM_PADDING;
|
|
171
|
+
const placedStores = stores.map((store, index) => ({
|
|
172
|
+
store,
|
|
173
|
+
box: {
|
|
174
|
+
x: laneLefts[index] ?? DIAGRAM_MARGIN,
|
|
175
|
+
y: laneTop,
|
|
176
|
+
width: laneBoxWidth,
|
|
177
|
+
height: laneBottom - laneTop,
|
|
178
|
+
},
|
|
179
|
+
}));
|
|
180
|
+
const corridors = placedStores.map(({ box }, index) => ({
|
|
181
|
+
left: box.x + LANE_PADDING_X - GUTTER - extra(index),
|
|
182
|
+
right: box.x + LANE_PADDING_X,
|
|
183
|
+
}));
|
|
184
|
+
const lastContentRight = (placedStores[placedStores.length - 1]?.box.x ?? DIAGRAM_MARGIN) + LANE_PADDING_X + LANE_CONTENT_WIDTH;
|
|
185
|
+
corridors.push({ left: lastContentRight, right: lastContentRight + GUTTER + extra(stores.length) });
|
|
186
|
+
return {
|
|
187
|
+
width: Math.ceil(contentRight + DIAGRAM_MARGIN),
|
|
188
|
+
height: Math.ceil(laneBottom + DIAGRAM_MARGIN),
|
|
189
|
+
stores: placedStores,
|
|
190
|
+
tables,
|
|
191
|
+
corridors,
|
|
192
|
+
laneTop,
|
|
193
|
+
};
|
|
194
|
+
};
|
|
195
|
+
const portOf = (layout, table, column) => {
|
|
196
|
+
const placed = layout.tables.find((candidate) => candidate.table.id === table);
|
|
197
|
+
const row = placed?.columns.find((candidate) => candidate.column.name === column);
|
|
198
|
+
return placed === undefined || row === undefined ? undefined : { table: placed, row };
|
|
199
|
+
};
|
|
200
|
+
const faceX = (box, side) => (side === "left" ? box.x : box.x + box.width);
|
|
201
|
+
/** Whether a corridor's run could carry a pill of this width without the pill crossing the cards either side. */
|
|
202
|
+
const pillFitsCorridor = (label) => label === undefined || pillSize(label).width + PILL_CARD_CLEARANCE * 2 <= GUTTER;
|
|
203
|
+
/**
|
|
204
|
+
* Where a route goes, from lane indices alone. A neighbouring lane is reached
|
|
205
|
+
* through the corridor between; the same lane steps out into the corridor
|
|
206
|
+
* beside it and back; a lane further away is crossed above the lanes.
|
|
207
|
+
*
|
|
208
|
+
* A labelled relation whose pill would not fit a corridor also crosses above,
|
|
209
|
+
* entering its target from the far face so the top run is a lane wide: the
|
|
210
|
+
* one straight run long enough to carry its words clear of every card.
|
|
211
|
+
*/
|
|
212
|
+
const planLanes = (la, lb, last, label) => {
|
|
213
|
+
const lift = !pillFitsCorridor(label);
|
|
214
|
+
if (la === lb) {
|
|
215
|
+
// ponytail: the corridor to the right, or the left for the last lane; a one-lane
|
|
216
|
+
// diagram with many self-keys gets a busy corridor, widen it when that shows.
|
|
217
|
+
const corridor = la < last ? la + 1 : la;
|
|
218
|
+
const side = corridor === la + 1 ? "right" : "left";
|
|
219
|
+
if (!lift)
|
|
220
|
+
return { fromSide: side, toSide: side, corridors: [corridor], over: false };
|
|
221
|
+
const farSide = side === "right" ? "left" : "right";
|
|
222
|
+
return { fromSide: side, toSide: farSide, corridors: [corridor, farSide === "left" ? lb : lb + 1], over: true };
|
|
223
|
+
}
|
|
224
|
+
const rightward = la < lb;
|
|
225
|
+
const fromSide = rightward ? "right" : "left";
|
|
226
|
+
const nearSide = rightward ? "left" : "right";
|
|
227
|
+
if (Math.abs(la - lb) === 1 && !lift)
|
|
228
|
+
return { fromSide, toSide: nearSide, corridors: [Math.max(la, lb)], over: false };
|
|
229
|
+
if (Math.abs(la - lb) === 1)
|
|
230
|
+
return { fromSide, toSide: fromSide, corridors: rightward ? [la + 1, lb + 1] : [la, lb], over: true };
|
|
231
|
+
return { fromSide, toSide: nearSide, corridors: rightward ? [la + 1, lb] : [la, lb + 1], over: true };
|
|
232
|
+
};
|
|
233
|
+
const plan = (layout, relation) => {
|
|
234
|
+
const from = portOf(layout, relation.from.table, relation.from.column);
|
|
235
|
+
const to = portOf(layout, relation.to.table, relation.to.column);
|
|
236
|
+
if (from === undefined || to === undefined)
|
|
237
|
+
return undefined;
|
|
238
|
+
const lanes = planLanes(from.table.laneIndex, to.table.laneIndex, layout.stores.length - 1, relation.label);
|
|
239
|
+
const end = (port, side) => ({ x: faceX(port.table.box, side), y: port.row.centre, side });
|
|
240
|
+
return {
|
|
241
|
+
relation,
|
|
242
|
+
from: end(from, lanes.fromSide),
|
|
243
|
+
to: end(to, lanes.toSide),
|
|
244
|
+
corridors: lanes.corridors,
|
|
245
|
+
over: lanes.over ? 0 : undefined,
|
|
246
|
+
};
|
|
247
|
+
};
|
|
248
|
+
const spread = (left, right, count) => {
|
|
249
|
+
// The layout widened the corridor for its legs, so the pitch never falls below the floor here.
|
|
250
|
+
const room = right - left - TRACK_CLEARANCE * 2;
|
|
251
|
+
const pitch = count < 2 ? 0 : Math.min(TRACK_PITCH_MAX, room / (count - 1));
|
|
252
|
+
const start = (left + right) / 2 - (pitch * (count - 1)) / 2;
|
|
253
|
+
return Array.from({ length: count }, (_, index) => start + index * pitch);
|
|
254
|
+
};
|
|
255
|
+
/**
|
|
256
|
+
* A pill is horizontal, so it sits on a horizontal run: the top run of a
|
|
257
|
+
* route that crosses above the lanes, whatever its other legs measure, and
|
|
258
|
+
* otherwise the longest level leg. A corridor route with no level run that
|
|
259
|
+
* holds the pill is what sent the route over the top in the first place.
|
|
260
|
+
*/
|
|
261
|
+
const pillAnchor = (waypoints, over) => {
|
|
262
|
+
const legs = waypoints.flatMap((point, index) => {
|
|
263
|
+
const previous = waypoints[index - 1];
|
|
264
|
+
return previous === undefined || previous.y !== point.y ? [] : [{ from: previous, to: point }];
|
|
265
|
+
});
|
|
266
|
+
const chosen = legs.reduce((best, leg) => {
|
|
267
|
+
if (best === undefined)
|
|
268
|
+
return leg;
|
|
269
|
+
if (over)
|
|
270
|
+
return leg.from.y < best.from.y ? leg : best;
|
|
271
|
+
return Math.abs(leg.to.x - leg.from.x) > Math.abs(best.to.x - best.from.x) ? leg : best;
|
|
272
|
+
}, undefined);
|
|
273
|
+
const first = waypoints[0] ?? { x: 0, y: 0 };
|
|
274
|
+
return chosen === undefined ? first : { x: (chosen.from.x + chosen.to.x) / 2, y: chosen.from.y };
|
|
275
|
+
};
|
|
276
|
+
export const routeRelations = (layout, relations) => {
|
|
277
|
+
const plans = relations.flatMap((relation) => {
|
|
278
|
+
const planned = plan(layout, relation);
|
|
279
|
+
return planned === undefined ? [] : [planned];
|
|
280
|
+
});
|
|
281
|
+
// A trunk is every route that lands on one column from one side in one tone, from TRUNK_MIN up.
|
|
282
|
+
const trunkOf = new Map();
|
|
283
|
+
{
|
|
284
|
+
const groups = new Map();
|
|
285
|
+
for (const route of plans) {
|
|
286
|
+
const key = trunkKey(route.relation, route.to.side);
|
|
287
|
+
groups.set(key, [...(groups.get(key) ?? []), route]);
|
|
288
|
+
}
|
|
289
|
+
for (const [key, group] of groups)
|
|
290
|
+
if (group.length >= TRUNK_MIN)
|
|
291
|
+
for (const route of group)
|
|
292
|
+
trunkOf.set(route, key);
|
|
293
|
+
}
|
|
294
|
+
/** A trunk's routes share a track and a landing, so they are one unit where they gather. */
|
|
295
|
+
const unitOf = (route, leg) => leg === route.corridors.length - 1 ? (trunkOf.get(route) ?? route) : route;
|
|
296
|
+
// What arrives on one column fans out a few pixels so each arrival keeps its own head.
|
|
297
|
+
const byTarget = new Map();
|
|
298
|
+
for (const route of plans) {
|
|
299
|
+
const key = `${route.relation.to.table}\u0000${route.relation.to.column}`;
|
|
300
|
+
const unit = trunkOf.get(route) ?? route;
|
|
301
|
+
const units = byTarget.get(key) ?? [];
|
|
302
|
+
if (!units.includes(unit))
|
|
303
|
+
byTarget.set(key, [...units, unit]);
|
|
304
|
+
}
|
|
305
|
+
const firstY = (unit) => typeof unit === "string"
|
|
306
|
+
? Math.min(...plans.filter((route) => trunkOf.get(route) === unit).map((route) => route.from.y))
|
|
307
|
+
: unit.from.y;
|
|
308
|
+
const landing = new Map();
|
|
309
|
+
for (const units of byTarget.values()) {
|
|
310
|
+
const sorted = [...units].sort((a, b) => firstY(a) - firstY(b));
|
|
311
|
+
const pitch = Math.min(PORT_FAN_MAX, (TABLE_ROW_HEIGHT - 2) / Math.max(1, sorted.length - 1));
|
|
312
|
+
sorted.forEach((unit, index) => {
|
|
313
|
+
for (const route of plans)
|
|
314
|
+
if ((trunkOf.get(route) ?? route) === unit)
|
|
315
|
+
landing.set(route, route.to.y + (index - (sorted.length - 1) / 2) * pitch);
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
// One track per vertical leg a corridor carries, ordered by where the leg lands.
|
|
319
|
+
const tracks = new Map();
|
|
320
|
+
layout.corridors.forEach((corridor, index) => {
|
|
321
|
+
const units = [];
|
|
322
|
+
const members = [];
|
|
323
|
+
plans.forEach((route) => route.corridors.forEach((at, leg) => {
|
|
324
|
+
if (at !== index)
|
|
325
|
+
return;
|
|
326
|
+
const unit = unitOf(route, leg);
|
|
327
|
+
if (!units.includes(unit))
|
|
328
|
+
units.push(unit);
|
|
329
|
+
members.push({ route, leg, unit });
|
|
330
|
+
}));
|
|
331
|
+
const landingOf = (unit) => typeof unit === "string"
|
|
332
|
+
? (landing.get(plans.find((route) => trunkOf.get(route) === unit) ?? plans[0]) ?? 0)
|
|
333
|
+
: (landing.get(unit) ?? 0);
|
|
334
|
+
units.sort((a, b) => landingOf(a) - landingOf(b) || firstY(a) - firstY(b));
|
|
335
|
+
const xs = spread(corridor.left, corridor.right, units.length);
|
|
336
|
+
for (const { route, leg, unit } of members) {
|
|
337
|
+
const own = tracks.get(route) ?? [];
|
|
338
|
+
own[leg] = xs[units.indexOf(unit)] ?? (corridor.left + corridor.right) / 2;
|
|
339
|
+
tracks.set(route, own);
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
// One head per trunk: the member that lands nearest its port carries it.
|
|
343
|
+
const heads = new Set();
|
|
344
|
+
for (const route of plans) {
|
|
345
|
+
const trunk = trunkOf.get(route);
|
|
346
|
+
if (trunk === undefined) {
|
|
347
|
+
heads.add(route);
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
const members = plans.filter((candidate) => trunkOf.get(candidate) === trunk);
|
|
351
|
+
const nearest = members.reduce((best, candidate) => Math.abs(candidate.from.y - candidate.to.y) < Math.abs(best.from.y - best.to.y) ? candidate : best);
|
|
352
|
+
heads.add(nearest);
|
|
353
|
+
}
|
|
354
|
+
let overCount = 0;
|
|
355
|
+
return plans.map((route) => {
|
|
356
|
+
const [first, second] = tracks.get(route) ?? [];
|
|
357
|
+
const x1 = first ?? route.from.x;
|
|
358
|
+
const landY = landing.get(route) ?? route.to.y;
|
|
359
|
+
const start = { x: route.from.x, y: route.from.y };
|
|
360
|
+
const end = { x: route.to.x, y: landY };
|
|
361
|
+
const waypoints = route.over === undefined
|
|
362
|
+
? [start, { x: x1, y: start.y }, { x: x1, y: end.y }, end]
|
|
363
|
+
: (() => {
|
|
364
|
+
const top = layout.laneTop - OVER_CLEARANCE - overCount * OVER_PITCH;
|
|
365
|
+
overCount += 1;
|
|
366
|
+
const x2 = second ?? route.to.x;
|
|
367
|
+
return [start, { x: x1, y: start.y }, { x: x1, y: top }, { x: x2, y: top }, { x: x2, y: end.y }, end];
|
|
368
|
+
})();
|
|
369
|
+
const curve = curveThrough(waypoints);
|
|
370
|
+
const label = route.relation.label;
|
|
371
|
+
const pill = label === undefined
|
|
372
|
+
? undefined
|
|
373
|
+
: (() => {
|
|
374
|
+
const size = pillSize(label);
|
|
375
|
+
const anchor = pillAnchor(waypoints, route.over !== undefined);
|
|
376
|
+
return { x: anchor.x - size.width / 2, y: anchor.y - size.height / 2, ...size };
|
|
377
|
+
})();
|
|
378
|
+
return { relation: route.relation, path: pathOf(curve), curve, waypoints, pill, head: heads.has(route) };
|
|
379
|
+
});
|
|
380
|
+
};
|
|
381
|
+
//# sourceMappingURL=datamodel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"datamodel.js","sourceRoot":"","sources":["../../src/layout/datamodel.ts"],"names":[],"mappings":"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"}
|
package/dist/layout/edges.d.ts
CHANGED
|
@@ -25,6 +25,7 @@ export type RoutedEdge = {
|
|
|
25
25
|
/** Centre of the longest straight run — where a pill with no room on its route starts looking. */
|
|
26
26
|
labelAnchor: Point | undefined;
|
|
27
27
|
};
|
|
28
|
+
export declare const pathOf: (curve: Curve) => string;
|
|
28
29
|
/**
|
|
29
30
|
* A box the route cannot leave. A cubic stays inside the hull of its own
|
|
30
31
|
* control points, so taking every point of every segment is a bound rather
|
|
@@ -32,6 +33,13 @@ export type RoutedEdge = {
|
|
|
32
33
|
* off the edge would simply be clipped.
|
|
33
34
|
*/
|
|
34
35
|
export declare const curveBounds: (curve: Curve) => Box;
|
|
36
|
+
/**
|
|
37
|
+
* The polyline as one continuous line: long runs stay dead straight and only
|
|
38
|
+
* the turns curve, each bend sized by the shorter of its two legs. Deriving
|
|
39
|
+
* the radius from the longer leg is the known failure — it balloons a route
|
|
40
|
+
* with one short leg clear out of the corridor the planner put it in.
|
|
41
|
+
*/
|
|
42
|
+
export declare const curveThrough: (points: readonly Point[]) => Curve;
|
|
35
43
|
export type RetiredRoutes = ReadonlyMap<string, "direct" | "exile">;
|
|
36
44
|
/**
|
|
37
45
|
* Direct or exile for each retired connection, whichever costs less in
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edges.d.ts","sourceRoot":"","sources":["../../src/layout/edges.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAYzD,OAAO,EAAoB,KAAK,GAAG,EAAE,KAAK,KAAK,EAAa,MAAM,gBAAgB,CAAC;AACnF,OAAO,KAAK,EAAE,kBAAkB,EAAsC,MAAM,mBAAmB,CAAC;AAGhG;;;GAGG;AACH,KAAK,OAAO,GACR;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,KAAK,CAAA;CAAE,GAC3B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,KAAK,CAAC;IAAC,EAAE,EAAE,KAAK,CAAA;CAAE,CAAC;AAE9D,MAAM,MAAM,KAAK,GAAG;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,OAAO,EAAE,CAAA;CAAE,CAAC;AAEzD,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,KAAK,CAAC;IACb,kGAAkG;IAClG,WAAW,EAAE,KAAK,GAAG,SAAS,CAAC;CAChC,CAAC;
|
|
1
|
+
{"version":3,"file":"edges.d.ts","sourceRoot":"","sources":["../../src/layout/edges.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAYzD,OAAO,EAAoB,KAAK,GAAG,EAAE,KAAK,KAAK,EAAa,MAAM,gBAAgB,CAAC;AACnF,OAAO,KAAK,EAAE,kBAAkB,EAAsC,MAAM,mBAAmB,CAAC;AAGhG;;;GAGG;AACH,KAAK,OAAO,GACR;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,KAAK,CAAA;CAAE,GAC3B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,KAAK,CAAC;IAAC,EAAE,EAAE,KAAK,CAAA;CAAE,CAAC;AAE9D,MAAM,MAAM,KAAK,GAAG;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,OAAO,EAAE,CAAA;CAAE,CAAC;AAEzD,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,KAAK,CAAC;IACb,kGAAkG;IAClG,WAAW,EAAE,KAAK,GAAG,SAAS,CAAC;CAChC,CAAC;AAiCF,eAAO,MAAM,MAAM,UAAW,KAAK,KAAG,MAiBzB,CAAC;AAEd;;;;;GAKG;AACH,eAAO,MAAM,WAAW,UAAW,KAAK,KAAG,GAoB1C,CAAC;AAkbF;;;;;GAKG;AACH,eAAO,MAAM,YAAY,WAAY,SAAS,KAAK,EAAE,KAAG,KAqCvD,CAAC;AAkBF,MAAM,MAAM,aAAa,GAAG,WAAW,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAC;AAKpE;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,UACvB,SAAS,SAAS,EAAE,UACnB,kBAAkB,KACzB,aAqCF,CAAC;AAYF,eAAO,MAAM,UAAU,UACd,SAAS,SAAS,EAAE,UACnB,kBAAkB,WACjB,aAAa,KACrB,UAAU,EAA8C,CAAC;AAE5D,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,gEAAgE;IAChE,eAAe,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC;CACzD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,cAAc,UAClB,SAAS,SAAS,EAAE,UACnB,kBAAkB,WACjB,aAAa,KACrB,cAA+D,CAAC;AAEnE,0DAA0D;AAC1D,eAAO,MAAM,aAAa,UACjB,SAAS,SAAS,EAAE,UACnB,kBAAkB,WACjB,aAAa,KACrB;IAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAAC,OAAO,EAAE,cAAc,CAAA;CAsBjD,CAAC"}
|
package/dist/layout/edges.js
CHANGED
|
@@ -30,7 +30,7 @@ const pointAt = (curve, t) => {
|
|
|
30
30
|
return curve.from;
|
|
31
31
|
return pointOnSegment(segmentStart(curve, index), segment, scaled - index);
|
|
32
32
|
};
|
|
33
|
-
const pathOf = (curve) => `M${coord(curve.from.x)},${coord(curve.from.y)}` +
|
|
33
|
+
export const pathOf = (curve) => `M${coord(curve.from.x)},${coord(curve.from.y)}` +
|
|
34
34
|
curve.segments
|
|
35
35
|
.map((segment) => {
|
|
36
36
|
switch (segment.kind) {
|
|
@@ -406,7 +406,7 @@ const KAPPA = 0.5523;
|
|
|
406
406
|
* the radius from the longer leg is the known failure — it balloons a route
|
|
407
407
|
* with one short leg clear out of the corridor the planner put it in.
|
|
408
408
|
*/
|
|
409
|
-
const curveThrough = (points) => {
|
|
409
|
+
export const curveThrough = (points) => {
|
|
410
410
|
const first = points[0] ?? { x: 0, y: 0 };
|
|
411
411
|
const segments = [];
|
|
412
412
|
for (let index = 1; index < points.length - 1; index += 1) {
|