@zukhruf/diagram 0.3.32 → 0.3.34
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/README.md +98 -52
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/compiler/diagram-compile.d.ts +3 -4
- package/dist/lib/compiler/diagram-compile.d.ts.map +1 -1
- package/dist/lib/compiler/diagram-compile.js +85 -370
- package/dist/lib/compiler/diagram-compile.js.map +1 -1
- package/dist/lib/layouts/graph/attach.d.ts +25 -0
- package/dist/lib/layouts/graph/attach.d.ts.map +1 -0
- package/dist/lib/layouts/graph/attach.js +272 -0
- package/dist/lib/layouts/graph/attach.js.map +1 -0
- package/dist/lib/layouts/graph/connections.d.ts +45 -0
- package/dist/lib/layouts/graph/connections.d.ts.map +1 -0
- package/dist/lib/layouts/graph/connections.js +138 -0
- package/dist/lib/layouts/graph/connections.js.map +1 -0
- package/dist/lib/layouts/graph/graph-layout-result.d.ts +5 -3
- package/dist/lib/layouts/graph/graph-layout-result.d.ts.map +1 -1
- package/dist/lib/layouts/graph/graph-layout-result.js.map +1 -1
- package/dist/lib/layouts/graph/gutters.js +41 -22
- package/dist/lib/layouts/graph/gutters.js.map +1 -1
- package/dist/lib/layouts/graph/labels.d.ts +23 -0
- package/dist/lib/layouts/graph/labels.d.ts.map +1 -0
- package/dist/lib/layouts/graph/labels.js +120 -0
- package/dist/lib/layouts/graph/labels.js.map +1 -0
- package/dist/lib/layouts/graph/layout.d.ts +1 -1
- package/dist/lib/layouts/graph/layout.d.ts.map +1 -1
- package/dist/lib/layouts/graph/layout.js +37 -12
- package/dist/lib/layouts/graph/layout.js.map +1 -1
- package/dist/lib/layouts/graph/measure.d.ts +15 -11
- package/dist/lib/layouts/graph/measure.d.ts.map +1 -1
- package/dist/lib/layouts/graph/measure.js +82 -38
- package/dist/lib/layouts/graph/measure.js.map +1 -1
- package/dist/lib/layouts/graph/min-heap.d.ts +8 -0
- package/dist/lib/layouts/graph/min-heap.d.ts.map +1 -0
- package/dist/lib/layouts/graph/min-heap.js +56 -0
- package/dist/lib/layouts/graph/min-heap.js.map +1 -0
- package/dist/lib/layouts/graph/node-content.d.ts +2 -3
- package/dist/lib/layouts/graph/node-content.d.ts.map +1 -1
- package/dist/lib/layouts/graph/node-content.js +67 -47
- package/dist/lib/layouts/graph/node-content.js.map +1 -1
- package/dist/lib/layouts/graph/path.d.ts +6 -0
- package/dist/lib/layouts/graph/path.d.ts.map +1 -0
- package/dist/lib/layouts/graph/path.js +53 -0
- package/dist/lib/layouts/graph/path.js.map +1 -0
- package/dist/lib/layouts/graph/round.d.ts +11 -0
- package/dist/lib/layouts/graph/round.d.ts.map +1 -0
- package/dist/lib/layouts/graph/round.js +181 -0
- package/dist/lib/layouts/graph/round.js.map +1 -0
- package/dist/lib/layouts/graph/route-search.d.ts +34 -0
- package/dist/lib/layouts/graph/route-search.d.ts.map +1 -0
- package/dist/lib/layouts/graph/route-search.js +208 -0
- package/dist/lib/layouts/graph/route-search.js.map +1 -0
- package/dist/lib/layouts/graph/route.d.ts +20 -0
- package/dist/lib/layouts/graph/route.d.ts.map +1 -0
- package/dist/lib/layouts/graph/route.js +276 -0
- package/dist/lib/layouts/graph/route.js.map +1 -0
- package/dist/lib/layouts/graph/sides.d.ts +28 -0
- package/dist/lib/layouts/graph/sides.d.ts.map +1 -0
- package/dist/lib/layouts/graph/sides.js +98 -0
- package/dist/lib/layouts/graph/sides.js.map +1 -0
- package/dist/lib/layouts/timeline/timeline-layout.d.ts +2 -1
- package/dist/lib/layouts/timeline/timeline-layout.d.ts.map +1 -1
- package/dist/lib/layouts/timeline/timeline-layout.js +9 -4
- package/dist/lib/layouts/timeline/timeline-layout.js.map +1 -1
- package/dist/lib/model/diagram-ir.d.ts +19 -156
- package/dist/lib/model/diagram-ir.d.ts.map +1 -1
- package/dist/lib/model/diagram-ir.js.map +1 -1
- package/dist/lib/model/validate-graph.d.ts +7 -0
- package/dist/lib/model/validate-graph.d.ts.map +1 -0
- package/dist/lib/model/validate-graph.js +54 -0
- package/dist/lib/model/validate-graph.js.map +1 -0
- package/dist/lib/react/Diagram.d.ts +3 -9
- package/dist/lib/react/Diagram.d.ts.map +1 -1
- package/dist/lib/react/Diagram.js +1 -13
- package/dist/lib/react/Diagram.js.map +1 -1
- package/dist/lib/react/diagram-types.d.ts +17 -46
- package/dist/lib/react/diagram-types.d.ts.map +1 -1
- package/dist/lib/react/diagram-types.js.map +1 -1
- package/dist/lib/renderers/canvas/graph-canvas.d.ts +2 -5
- package/dist/lib/renderers/canvas/graph-canvas.d.ts.map +1 -1
- package/dist/lib/renderers/canvas/graph-canvas.js +68 -43
- package/dist/lib/renderers/canvas/graph-canvas.js.map +1 -1
- package/dist/lib/renderers/html/graph-html.d.ts +2 -3
- package/dist/lib/renderers/html/graph-html.d.ts.map +1 -1
- package/dist/lib/renderers/html/graph-html.js +298 -289
- package/dist/lib/renderers/html/graph-html.js.map +1 -1
- package/dist/lib/renderers/shared/graph-parts.d.ts +3 -1
- package/dist/lib/renderers/shared/graph-parts.d.ts.map +1 -1
- package/dist/lib/renderers/shared/graph-parts.js +350 -418
- package/dist/lib/renderers/shared/graph-parts.js.map +1 -1
- package/dist/lib/renderers/shared/node-parts.d.ts +5 -6
- package/dist/lib/renderers/shared/node-parts.d.ts.map +1 -1
- package/dist/lib/renderers/shared/node-parts.js +112 -190
- package/dist/lib/renderers/shared/node-parts.js.map +1 -1
- package/dist/lib/renderers/shared/run-spans.js +2 -2
- package/dist/lib/renderers/shared/run-spans.js.map +1 -1
- package/dist/lib/renderers/shared/text-runs.d.ts +0 -6
- package/dist/lib/renderers/shared/text-runs.d.ts.map +1 -1
- package/dist/lib/renderers/shared/text-runs.js +0 -12
- package/dist/lib/renderers/shared/text-runs.js.map +1 -1
- package/dist/lib/renderers/svg/graph-svg.d.ts +1 -3
- package/dist/lib/renderers/svg/graph-svg.d.ts.map +1 -1
- package/dist/lib/renderers/svg/graph-svg.js +66 -80
- package/dist/lib/renderers/svg/graph-svg.js.map +1 -1
- package/dist/lib/renderers/svg/timeline-svg.d.ts.map +1 -1
- package/dist/lib/renderers/svg/timeline-svg.js +7 -5
- package/dist/lib/renderers/svg/timeline-svg.js.map +1 -1
- package/package.json +1 -1
- package/dist/lib/layouts/graph/graph-layout.d.ts +0 -154
- package/dist/lib/layouts/graph/graph-layout.d.ts.map +0 -1
- package/dist/lib/layouts/graph/graph-layout.js +0 -2340
- package/dist/lib/layouts/graph/graph-layout.js.map +0 -1
- package/dist/lib/layouts/graph/legacy-graph-layout.d.ts +0 -6
- package/dist/lib/layouts/graph/legacy-graph-layout.d.ts.map +0 -1
- package/dist/lib/layouts/graph/legacy-graph-layout.js +0 -542
- package/dist/lib/layouts/graph/legacy-graph-layout.js.map +0 -1
- package/dist/lib/layouts/text-metrics.d.ts +0 -7
- package/dist/lib/layouts/text-metrics.d.ts.map +0 -1
- package/dist/lib/layouts/text-metrics.js +0 -40
- package/dist/lib/layouts/text-metrics.js.map +0 -1
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { round } from "./round.js";
|
|
2
|
+
|
|
3
|
+
/** The radius of the rounded corner the SVG path draws at each bend. */
|
|
4
|
+
const CORNER_RADIUS = 8;
|
|
5
|
+
|
|
6
|
+
/** Drops every point that lies on the straight line through its neighbours. */
|
|
7
|
+
export function simplifyPath(path) {
|
|
8
|
+
if (path.length < 3) return path;
|
|
9
|
+
const result = [path[0]];
|
|
10
|
+
for (const [index, current] of path.slice(1, -1).entries()) {
|
|
11
|
+
const previous = result.at(-1);
|
|
12
|
+
const next = path[index + 2];
|
|
13
|
+
const cross = (current.x - previous.x) * (next.y - current.y) - (current.y - previous.y) * (next.x - current.x);
|
|
14
|
+
if (cross !== 0) result.push(current);
|
|
15
|
+
}
|
|
16
|
+
result.push(path.at(-1));
|
|
17
|
+
return result;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** An SVG path through the points, with each bend rounded, and each number to the layout's precision. */
|
|
21
|
+
export function pathToSvg(points) {
|
|
22
|
+
const [first, ...rest] = points;
|
|
23
|
+
if (!first) return '';
|
|
24
|
+
const at = ({
|
|
25
|
+
x,
|
|
26
|
+
y
|
|
27
|
+
}) => `${round(x)} ${round(y)}`;
|
|
28
|
+
const parts = [`M ${at(first)}`];
|
|
29
|
+
for (const [index, current] of rest.slice(0, -1).entries()) {
|
|
30
|
+
const previous = points[index];
|
|
31
|
+
const next = points[index + 2];
|
|
32
|
+
const dpx = current.x - previous.x;
|
|
33
|
+
const dpy = current.y - previous.y;
|
|
34
|
+
const dnx = next.x - current.x;
|
|
35
|
+
const dny = next.y - current.y;
|
|
36
|
+
const lp = Math.hypot(dpx, dpy);
|
|
37
|
+
const ln = Math.hypot(dnx, dny);
|
|
38
|
+
const r = Math.min(CORNER_RADIUS, lp / 2, ln / 2);
|
|
39
|
+
const cs = {
|
|
40
|
+
x: current.x - dpx / lp * r,
|
|
41
|
+
y: current.y - dpy / lp * r
|
|
42
|
+
};
|
|
43
|
+
const ce = {
|
|
44
|
+
x: current.x + dnx / ln * r,
|
|
45
|
+
y: current.y + dny / ln * r
|
|
46
|
+
};
|
|
47
|
+
parts.push(`L ${at(cs)}`, `Q ${at(current)} ${at(ce)}`);
|
|
48
|
+
}
|
|
49
|
+
const last = rest.at(-1);
|
|
50
|
+
if (last) parts.push(`L ${at(last)}`);
|
|
51
|
+
return parts.join(' ');
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path.js","names":["round","CORNER_RADIUS","simplifyPath","path","length","result","index","current","slice","entries","previous","at","next","cross","x","y","push","pathToSvg","points","first","rest","parts","dpx","dpy","dnx","dny","lp","Math","hypot","ln","r","min","cs","ce","last","join"],"sources":["../../../../src/lib/layouts/graph/path.ts"],"sourcesContent":["import type { Point } from '../../model/diagram-ir.ts';\nimport { round } from './round.ts';\n\n/** The radius of the rounded corner the SVG path draws at each bend. */\nconst CORNER_RADIUS = 8;\n\n/** Drops every point that lies on the straight line through its neighbours. */\nexport function simplifyPath(path: Point[]): Point[] {\n if (path.length < 3) return path;\n const result: Point[] = [path[0]!];\n for (const [index, current] of path.slice(1, -1).entries()) {\n const previous = result.at(-1)!;\n const next = path[index + 2]!;\n const cross =\n (current.x - previous.x) * (next.y - current.y) -\n (current.y - previous.y) * (next.x - current.x);\n if (cross !== 0) result.push(current);\n }\n result.push(path.at(-1)!);\n return result;\n}\n\n/** An SVG path through the points, with each bend rounded, and each number to the layout's precision. */\nexport function pathToSvg(points: Point[]): string {\n const [first, ...rest] = points;\n if (!first) return '';\n const at = ({ x, y }: Point) => `${round(x)} ${round(y)}`;\n const parts = [`M ${at(first)}`];\n for (const [index, current] of rest.slice(0, -1).entries()) {\n const previous = points[index]!;\n const next = points[index + 2]!;\n const dpx = current.x - previous.x;\n const dpy = current.y - previous.y;\n const dnx = next.x - current.x;\n const dny = next.y - current.y;\n const lp = Math.hypot(dpx, dpy);\n const ln = Math.hypot(dnx, dny);\n const r = Math.min(CORNER_RADIUS, lp / 2, ln / 2);\n const cs = { x: current.x - (dpx / lp) * r, y: current.y - (dpy / lp) * r };\n const ce = { x: current.x + (dnx / ln) * r, y: current.y + (dny / ln) * r };\n parts.push(`L ${at(cs)}`, `Q ${at(current)} ${at(ce)}`);\n }\n const last = rest.at(-1);\n if (last) parts.push(`L ${at(last)}`);\n return parts.join(' ');\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { GraphLayout } from './graph-layout-result.ts';
|
|
2
|
+
import type { RoutedGraph } from './route.ts';
|
|
3
|
+
/** The value to DECIMALS decimals; `+ 0` turns a rounded -0 into 0. */
|
|
4
|
+
export declare function round(value: number): number;
|
|
5
|
+
/**
|
|
6
|
+
* The layout with every coordinate rounded to DECIMALS decimals, and each
|
|
7
|
+
* path drawn through the rounded points. The geometry before it keeps full
|
|
8
|
+
* precision, so the rounding happens once and does not drift.
|
|
9
|
+
*/
|
|
10
|
+
export declare function roundLayout(layout: Omit<GraphLayout, keyof RoutedGraph> & RoutedGraph): GraphLayout;
|
|
11
|
+
//# sourceMappingURL=round.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"round.d.ts","sourceRoot":"","sources":["../../../../src/lib/layouts/graph/round.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,WAAW,EAMZ,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAM9C,uEAAuE;AACvE,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,WAAW,CAAC,GAAG,WAAW,GACzD,WAAW,CAQb"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { pathToSvg } from "./path.js";
|
|
2
|
+
/** How many decimals every coordinate the layout returns keeps. */
|
|
3
|
+
const DECIMALS = 2;
|
|
4
|
+
const SCALE = 10 ** DECIMALS;
|
|
5
|
+
|
|
6
|
+
/** The value to DECIMALS decimals; `+ 0` turns a rounded -0 into 0. */
|
|
7
|
+
export function round(value) {
|
|
8
|
+
return Math.round(value * SCALE) / SCALE + 0;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The layout with every coordinate rounded to DECIMALS decimals, and each
|
|
13
|
+
* path drawn through the rounded points. The geometry before it keeps full
|
|
14
|
+
* precision, so the rounding happens once and does not drift.
|
|
15
|
+
*/
|
|
16
|
+
export function roundLayout(layout) {
|
|
17
|
+
return {
|
|
18
|
+
nodes: layout.nodes.map(roundNode),
|
|
19
|
+
groups: layout.groups.map(roundGroup),
|
|
20
|
+
edges: layout.edges.map(roundEdge),
|
|
21
|
+
leaders: layout.leaders.map(roundLeader),
|
|
22
|
+
viewBox: roundBox(layout.viewBox)
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function roundEdge({
|
|
26
|
+
points,
|
|
27
|
+
label,
|
|
28
|
+
badge,
|
|
29
|
+
...edge
|
|
30
|
+
}) {
|
|
31
|
+
const rounded = points.map(roundPoint);
|
|
32
|
+
return {
|
|
33
|
+
...edge,
|
|
34
|
+
points: rounded,
|
|
35
|
+
d: pathToSvg(rounded),
|
|
36
|
+
...(label && {
|
|
37
|
+
label: {
|
|
38
|
+
box: roundBox(label.box),
|
|
39
|
+
text: label.text.map(roundRun)
|
|
40
|
+
}
|
|
41
|
+
}),
|
|
42
|
+
...(badge && {
|
|
43
|
+
badge: {
|
|
44
|
+
box: roundBox(badge.box),
|
|
45
|
+
...(badge.icon && {
|
|
46
|
+
icon: roundBox(badge.icon)
|
|
47
|
+
}),
|
|
48
|
+
text: badge.text.map(roundRun)
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function roundLeader({
|
|
54
|
+
points,
|
|
55
|
+
...leader
|
|
56
|
+
}) {
|
|
57
|
+
const rounded = points.map(roundPoint);
|
|
58
|
+
return {
|
|
59
|
+
...leader,
|
|
60
|
+
points: rounded,
|
|
61
|
+
d: pathToSvg(rounded)
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function roundNode({
|
|
65
|
+
box,
|
|
66
|
+
visual,
|
|
67
|
+
frames,
|
|
68
|
+
icon,
|
|
69
|
+
text,
|
|
70
|
+
bullets,
|
|
71
|
+
contentBox,
|
|
72
|
+
caption,
|
|
73
|
+
ports,
|
|
74
|
+
appliance,
|
|
75
|
+
...node
|
|
76
|
+
}) {
|
|
77
|
+
return {
|
|
78
|
+
...node,
|
|
79
|
+
box: roundBox(box),
|
|
80
|
+
visual: roundBox(visual),
|
|
81
|
+
frames: frames.map(roundBox),
|
|
82
|
+
...(icon && {
|
|
83
|
+
icon: {
|
|
84
|
+
x: round(icon.x),
|
|
85
|
+
y: round(icon.y),
|
|
86
|
+
size: round(icon.size)
|
|
87
|
+
}
|
|
88
|
+
}),
|
|
89
|
+
text: text.map(roundRun),
|
|
90
|
+
bullets: bullets.map(roundPoint),
|
|
91
|
+
...(contentBox && {
|
|
92
|
+
contentBox: roundBox(contentBox)
|
|
93
|
+
}),
|
|
94
|
+
...(caption && {
|
|
95
|
+
caption: {
|
|
96
|
+
box: roundBox(caption.box),
|
|
97
|
+
framed: caption.framed,
|
|
98
|
+
text: caption.text.map(roundRun)
|
|
99
|
+
}
|
|
100
|
+
}),
|
|
101
|
+
ports: ports.map(roundPort),
|
|
102
|
+
...(appliance && {
|
|
103
|
+
appliance: {
|
|
104
|
+
body: appliance.body.map(roundPoint),
|
|
105
|
+
face: roundLine(appliance.face),
|
|
106
|
+
antenna: appliance.antenna.map(roundLine),
|
|
107
|
+
jacks: appliance.jacks.map(roundBox)
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function roundGroup({
|
|
113
|
+
rect,
|
|
114
|
+
band,
|
|
115
|
+
separator,
|
|
116
|
+
label,
|
|
117
|
+
dividers,
|
|
118
|
+
ports,
|
|
119
|
+
...group
|
|
120
|
+
}) {
|
|
121
|
+
return {
|
|
122
|
+
...group,
|
|
123
|
+
rect: roundBox(rect),
|
|
124
|
+
...(band && {
|
|
125
|
+
band: roundBox(band)
|
|
126
|
+
}),
|
|
127
|
+
...(separator && {
|
|
128
|
+
separator: roundLine(separator)
|
|
129
|
+
}),
|
|
130
|
+
label: label.map(roundRun),
|
|
131
|
+
dividers: dividers.map(roundLine),
|
|
132
|
+
ports: ports.map(roundPort)
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function roundPort({
|
|
136
|
+
point,
|
|
137
|
+
label,
|
|
138
|
+
...port
|
|
139
|
+
}) {
|
|
140
|
+
return {
|
|
141
|
+
...port,
|
|
142
|
+
point: roundPoint(point),
|
|
143
|
+
...(label && {
|
|
144
|
+
label: roundRun(label)
|
|
145
|
+
})
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
function roundRun(run) {
|
|
149
|
+
return {
|
|
150
|
+
...run,
|
|
151
|
+
x: round(run.x),
|
|
152
|
+
y: round(run.y),
|
|
153
|
+
bounds: roundBox(run.bounds)
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
function roundLine([a, b]) {
|
|
157
|
+
return [roundPoint(a), roundPoint(b)];
|
|
158
|
+
}
|
|
159
|
+
function roundPoint({
|
|
160
|
+
x,
|
|
161
|
+
y
|
|
162
|
+
}) {
|
|
163
|
+
return {
|
|
164
|
+
x: round(x),
|
|
165
|
+
y: round(y)
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
function roundBox({
|
|
169
|
+
x,
|
|
170
|
+
y,
|
|
171
|
+
w,
|
|
172
|
+
h
|
|
173
|
+
}) {
|
|
174
|
+
return {
|
|
175
|
+
x: round(x),
|
|
176
|
+
y: round(y),
|
|
177
|
+
w: round(w),
|
|
178
|
+
h: round(h)
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=round.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"round.js","names":["pathToSvg","DECIMALS","SCALE","round","value","Math","roundLayout","layout","nodes","map","roundNode","groups","roundGroup","edges","roundEdge","leaders","roundLeader","viewBox","roundBox","points","label","badge","edge","rounded","roundPoint","d","box","text","roundRun","icon","leader","visual","frames","bullets","contentBox","caption","ports","appliance","node","x","y","size","framed","roundPort","body","face","roundLine","antenna","jacks","rect","band","separator","dividers","group","point","port","run","bounds","a","b","w","h"],"sources":["../../../../src/lib/layouts/graph/round.ts"],"sourcesContent":["import type { Box, Point } from '../../model/diagram-ir.ts';\nimport type {\n EdgeLayout,\n GraphLayout,\n GroupLayout,\n LeaderLayout,\n NodeLayout,\n PortLayout,\n TextRun,\n} from './graph-layout-result.ts';\nimport { pathToSvg } from './path.ts';\nimport type { RoutedGraph } from './route.ts';\n\n/** How many decimals every coordinate the layout returns keeps. */\nconst DECIMALS = 2;\nconst SCALE = 10 ** DECIMALS;\n\n/** The value to DECIMALS decimals; `+ 0` turns a rounded -0 into 0. */\nexport function round(value: number): number {\n return Math.round(value * SCALE) / SCALE + 0;\n}\n\n/**\n * The layout with every coordinate rounded to DECIMALS decimals, and each\n * path drawn through the rounded points. The geometry before it keeps full\n * precision, so the rounding happens once and does not drift.\n */\nexport function roundLayout(\n layout: Omit<GraphLayout, keyof RoutedGraph> & RoutedGraph,\n): GraphLayout {\n return {\n nodes: layout.nodes.map(roundNode),\n groups: layout.groups.map(roundGroup),\n edges: layout.edges.map(roundEdge),\n leaders: layout.leaders.map(roundLeader),\n viewBox: roundBox(layout.viewBox),\n };\n}\n\nfunction roundEdge({\n points,\n label,\n badge,\n ...edge\n}: RoutedGraph['edges'][number]): EdgeLayout {\n const rounded = points.map(roundPoint);\n return {\n ...edge,\n points: rounded,\n d: pathToSvg(rounded),\n ...(label && {\n label: { box: roundBox(label.box), text: label.text.map(roundRun) },\n }),\n ...(badge && {\n badge: {\n box: roundBox(badge.box),\n ...(badge.icon && { icon: roundBox(badge.icon) }),\n text: badge.text.map(roundRun),\n },\n }),\n };\n}\n\nfunction roundLeader({\n points,\n ...leader\n}: RoutedGraph['leaders'][number]): LeaderLayout {\n const rounded = points.map(roundPoint);\n return { ...leader, points: rounded, d: pathToSvg(rounded) };\n}\n\nfunction roundNode({\n box,\n visual,\n frames,\n icon,\n text,\n bullets,\n contentBox,\n caption,\n ports,\n appliance,\n ...node\n}: NodeLayout): NodeLayout {\n return {\n ...node,\n box: roundBox(box),\n visual: roundBox(visual),\n frames: frames.map(roundBox),\n ...(icon && {\n icon: { x: round(icon.x), y: round(icon.y), size: round(icon.size) },\n }),\n text: text.map(roundRun),\n bullets: bullets.map(roundPoint),\n ...(contentBox && { contentBox: roundBox(contentBox) }),\n ...(caption && {\n caption: {\n box: roundBox(caption.box),\n framed: caption.framed,\n text: caption.text.map(roundRun),\n },\n }),\n ports: ports.map(roundPort),\n ...(appliance && {\n appliance: {\n body: appliance.body.map(roundPoint),\n face: roundLine(appliance.face),\n antenna: appliance.antenna.map(roundLine),\n jacks: appliance.jacks.map(roundBox),\n },\n }),\n };\n}\n\nfunction roundGroup({\n rect,\n band,\n separator,\n label,\n dividers,\n ports,\n ...group\n}: GroupLayout): GroupLayout {\n return {\n ...group,\n rect: roundBox(rect),\n ...(band && { band: roundBox(band) }),\n ...(separator && { separator: roundLine(separator) }),\n label: label.map(roundRun),\n dividers: dividers.map(roundLine),\n ports: ports.map(roundPort),\n };\n}\n\nfunction roundPort({ point, label, ...port }: PortLayout): PortLayout {\n return {\n ...port,\n point: roundPoint(point),\n ...(label && { label: roundRun(label) }),\n };\n}\n\nfunction roundRun(run: TextRun): TextRun {\n return {\n ...run,\n x: round(run.x),\n y: round(run.y),\n bounds: roundBox(run.bounds),\n };\n}\n\nfunction roundLine([a, b]: [Point, Point]): [Point, Point] {\n return [roundPoint(a), roundPoint(b)];\n}\n\nfunction roundPoint({ x, y }: Point): Point {\n return { x: round(x), y: round(y) };\n}\n\nfunction roundBox({ x, y, w, h }: Box): Box {\n return { x: round(x), y: round(y), w: round(w), h: round(h) };\n}\n"],"mappings":"AAUA,SAASA,SAAS,QAAQ,WAAW;AAGrC;AACA,MAAMC,QAAQ,GAAG,CAAC;AAClB,MAAMC,KAAK,GAAG,EAAE,IAAID,QAAQ;;AAE5B;AACA,OAAO,SAASE,KAAKA,CAACC,KAAa,EAAU;EAC3C,OAAOC,IAAI,CAACF,KAAK,CAACC,KAAK,GAAGF,KAAK,CAAC,GAAGA,KAAK,GAAG,CAAC;AAC9C;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASI,WAAWA,CACzBC,MAA0D,EAC7C;EACb,OAAO;IACLC,KAAK,EAAED,MAAM,CAACC,KAAK,CAACC,GAAG,CAACC,SAAS,CAAC;IAClCC,MAAM,EAAEJ,MAAM,CAACI,MAAM,CAACF,GAAG,CAACG,UAAU,CAAC;IACrCC,KAAK,EAAEN,MAAM,CAACM,KAAK,CAACJ,GAAG,CAACK,SAAS,CAAC;IAClCC,OAAO,EAAER,MAAM,CAACQ,OAAO,CAACN,GAAG,CAACO,WAAW,CAAC;IACxCC,OAAO,EAAEC,QAAQ,CAACX,MAAM,CAACU,OAAO;EAClC,CAAC;AACH;AAEA,SAASH,SAASA,CAAC;EACjBK,MAAM;EACNC,KAAK;EACLC,KAAK;EACL,GAAGC;AACyB,CAAC,EAAc;EAC3C,MAAMC,OAAO,GAAGJ,MAAM,CAACV,GAAG,CAACe,UAAU,CAAC;EACtC,OAAO;IACL,GAAGF,IAAI;IACPH,MAAM,EAAEI,OAAO;IACfE,CAAC,EAAEzB,SAAS,CAACuB,OAAO,CAAC;IACrB,IAAIH,KAAK,IAAI;MACXA,KAAK,EAAE;QAAEM,GAAG,EAAER,QAAQ,CAACE,KAAK,CAACM,GAAG,CAAC;QAAEC,IAAI,EAAEP,KAAK,CAACO,IAAI,CAAClB,GAAG,CAACmB,QAAQ;MAAE;IACpE,CAAC,CAAC;IACF,IAAIP,KAAK,IAAI;MACXA,KAAK,EAAE;QACLK,GAAG,EAAER,QAAQ,CAACG,KAAK,CAACK,GAAG,CAAC;QACxB,IAAIL,KAAK,CAACQ,IAAI,IAAI;UAAEA,IAAI,EAAEX,QAAQ,CAACG,KAAK,CAACQ,IAAI;QAAE,CAAC,CAAC;QACjDF,IAAI,EAAEN,KAAK,CAACM,IAAI,CAAClB,GAAG,CAACmB,QAAQ;MAC/B;IACF,CAAC;EACH,CAAC;AACH;AAEA,SAASZ,WAAWA,CAAC;EACnBG,MAAM;EACN,GAAGW;AAC2B,CAAC,EAAgB;EAC/C,MAAMP,OAAO,GAAGJ,MAAM,CAACV,GAAG,CAACe,UAAU,CAAC;EACtC,OAAO;IAAE,GAAGM,MAAM;IAAEX,MAAM,EAAEI,OAAO;IAAEE,CAAC,EAAEzB,SAAS,CAACuB,OAAO;EAAE,CAAC;AAC9D;AAEA,SAASb,SAASA,CAAC;EACjBgB,GAAG;EACHK,MAAM;EACNC,MAAM;EACNH,IAAI;EACJF,IAAI;EACJM,OAAO;EACPC,UAAU;EACVC,OAAO;EACPC,KAAK;EACLC,SAAS;EACT,GAAGC;AACO,CAAC,EAAc;EACzB,OAAO;IACL,GAAGA,IAAI;IACPZ,GAAG,EAAER,QAAQ,CAACQ,GAAG,CAAC;IAClBK,MAAM,EAAEb,QAAQ,CAACa,MAAM,CAAC;IACxBC,MAAM,EAAEA,MAAM,CAACvB,GAAG,CAACS,QAAQ,CAAC;IAC5B,IAAIW,IAAI,IAAI;MACVA,IAAI,EAAE;QAAEU,CAAC,EAAEpC,KAAK,CAAC0B,IAAI,CAACU,CAAC,CAAC;QAAEC,CAAC,EAAErC,KAAK,CAAC0B,IAAI,CAACW,CAAC,CAAC;QAAEC,IAAI,EAAEtC,KAAK,CAAC0B,IAAI,CAACY,IAAI;MAAE;IACrE,CAAC,CAAC;IACFd,IAAI,EAAEA,IAAI,CAAClB,GAAG,CAACmB,QAAQ,CAAC;IACxBK,OAAO,EAAEA,OAAO,CAACxB,GAAG,CAACe,UAAU,CAAC;IAChC,IAAIU,UAAU,IAAI;MAAEA,UAAU,EAAEhB,QAAQ,CAACgB,UAAU;IAAE,CAAC,CAAC;IACvD,IAAIC,OAAO,IAAI;MACbA,OAAO,EAAE;QACPT,GAAG,EAAER,QAAQ,CAACiB,OAAO,CAACT,GAAG,CAAC;QAC1BgB,MAAM,EAAEP,OAAO,CAACO,MAAM;QACtBf,IAAI,EAAEQ,OAAO,CAACR,IAAI,CAAClB,GAAG,CAACmB,QAAQ;MACjC;IACF,CAAC,CAAC;IACFQ,KAAK,EAAEA,KAAK,CAAC3B,GAAG,CAACkC,SAAS,CAAC;IAC3B,IAAIN,SAAS,IAAI;MACfA,SAAS,EAAE;QACTO,IAAI,EAAEP,SAAS,CAACO,IAAI,CAACnC,GAAG,CAACe,UAAU,CAAC;QACpCqB,IAAI,EAAEC,SAAS,CAACT,SAAS,CAACQ,IAAI,CAAC;QAC/BE,OAAO,EAAEV,SAAS,CAACU,OAAO,CAACtC,GAAG,CAACqC,SAAS,CAAC;QACzCE,KAAK,EAAEX,SAAS,CAACW,KAAK,CAACvC,GAAG,CAACS,QAAQ;MACrC;IACF,CAAC;EACH,CAAC;AACH;AAEA,SAASN,UAAUA,CAAC;EAClBqC,IAAI;EACJC,IAAI;EACJC,SAAS;EACT/B,KAAK;EACLgC,QAAQ;EACRhB,KAAK;EACL,GAAGiB;AACQ,CAAC,EAAe;EAC3B,OAAO;IACL,GAAGA,KAAK;IACRJ,IAAI,EAAE/B,QAAQ,CAAC+B,IAAI,CAAC;IACpB,IAAIC,IAAI,IAAI;MAAEA,IAAI,EAAEhC,QAAQ,CAACgC,IAAI;IAAE,CAAC,CAAC;IACrC,IAAIC,SAAS,IAAI;MAAEA,SAAS,EAAEL,SAAS,CAACK,SAAS;IAAE,CAAC,CAAC;IACrD/B,KAAK,EAAEA,KAAK,CAACX,GAAG,CAACmB,QAAQ,CAAC;IAC1BwB,QAAQ,EAAEA,QAAQ,CAAC3C,GAAG,CAACqC,SAAS,CAAC;IACjCV,KAAK,EAAEA,KAAK,CAAC3B,GAAG,CAACkC,SAAS;EAC5B,CAAC;AACH;AAEA,SAASA,SAASA,CAAC;EAAEW,KAAK;EAAElC,KAAK;EAAE,GAAGmC;AAAiB,CAAC,EAAc;EACpE,OAAO;IACL,GAAGA,IAAI;IACPD,KAAK,EAAE9B,UAAU,CAAC8B,KAAK,CAAC;IACxB,IAAIlC,KAAK,IAAI;MAAEA,KAAK,EAAEQ,QAAQ,CAACR,KAAK;IAAE,CAAC;EACzC,CAAC;AACH;AAEA,SAASQ,QAAQA,CAAC4B,GAAY,EAAW;EACvC,OAAO;IACL,GAAGA,GAAG;IACNjB,CAAC,EAAEpC,KAAK,CAACqD,GAAG,CAACjB,CAAC,CAAC;IACfC,CAAC,EAAErC,KAAK,CAACqD,GAAG,CAAChB,CAAC,CAAC;IACfiB,MAAM,EAAEvC,QAAQ,CAACsC,GAAG,CAACC,MAAM;EAC7B,CAAC;AACH;AAEA,SAASX,SAASA,CAAC,CAACY,CAAC,EAAEC,CAAC,CAAiB,EAAkB;EACzD,OAAO,CAACnC,UAAU,CAACkC,CAAC,CAAC,EAAElC,UAAU,CAACmC,CAAC,CAAC,CAAC;AACvC;AAEA,SAASnC,UAAUA,CAAC;EAAEe,CAAC;EAAEC;AAAS,CAAC,EAAS;EAC1C,OAAO;IAAED,CAAC,EAAEpC,KAAK,CAACoC,CAAC,CAAC;IAAEC,CAAC,EAAErC,KAAK,CAACqC,CAAC;EAAE,CAAC;AACrC;AAEA,SAAStB,QAAQA,CAAC;EAAEqB,CAAC;EAAEC,CAAC;EAAEoB,CAAC;EAAEC;AAAO,CAAC,EAAO;EAC1C,OAAO;IAAEtB,CAAC,EAAEpC,KAAK,CAACoC,CAAC,CAAC;IAAEC,CAAC,EAAErC,KAAK,CAACqC,CAAC,CAAC;IAAEoB,CAAC,EAAEzD,KAAK,CAACyD,CAAC,CAAC;IAAEC,CAAC,EAAE1D,KAAK,CAAC0D,CAAC;EAAE,CAAC;AAC/D","ignoreList":[]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Box, Point } from '../../model/diagram-ir.ts';
|
|
2
|
+
/** A direction of travel: right, left, down, up. */
|
|
3
|
+
export type Heading = 0 | 1 | 2 | 3;
|
|
4
|
+
/** The routing grid's pitch. */
|
|
5
|
+
export declare const GRID = 4;
|
|
6
|
+
export type RouteSearch = {
|
|
7
|
+
/** Only grid points inside this box are searched. */
|
|
8
|
+
window: Box;
|
|
9
|
+
/** Coordinates the grid holds besides every multiple of GRID: the route's own ends, slots and stubs. */
|
|
10
|
+
lines: {
|
|
11
|
+
x: number[];
|
|
12
|
+
y: number[];
|
|
13
|
+
};
|
|
14
|
+
/** No route passes a grid point strictly inside one of these. */
|
|
15
|
+
walls: Box[];
|
|
16
|
+
/** Segments of routes already drawn: a route may cross them at a cost, never run along them. */
|
|
17
|
+
runs: [Point, Point][];
|
|
18
|
+
/** Group rects and title bands: crossing or hugging their borders costs extra. */
|
|
19
|
+
borders: Box[];
|
|
20
|
+
start: Point;
|
|
21
|
+
/** The heading of the stub that reaches `start`. */
|
|
22
|
+
startHeading: Heading;
|
|
23
|
+
goal: Point;
|
|
24
|
+
/** The heading of the stub that leaves `goal` for the entry side. */
|
|
25
|
+
goalHeading: Heading;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* The cheapest orthogonal path from `start` to `goal` on a grid of GRID
|
|
29
|
+
* pitch, or undefined when the walls leave none. The search state is a grid
|
|
30
|
+
* point together with the heading that reached it, so a turn costs the same
|
|
31
|
+
* whichever way a point was reached.
|
|
32
|
+
*/
|
|
33
|
+
export declare function searchRoute(search: RouteSearch): Point[] | undefined;
|
|
34
|
+
//# sourceMappingURL=route-search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-search.d.ts","sourceRoot":"","sources":["../../../../src/lib/layouts/graph/route-search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAG5D,oDAAoD;AACpD,MAAM,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAEpC,gCAAgC;AAChC,eAAO,MAAM,IAAI,IAAI,CAAC;AA4BtB,MAAM,MAAM,WAAW,GAAG;IACxB,qDAAqD;IACrD,MAAM,EAAE,GAAG,CAAC;IACZ,wGAAwG;IACxG,KAAK,EAAE;QAAE,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACpC,iEAAiE;IACjE,KAAK,EAAE,GAAG,EAAE,CAAC;IACb,gGAAgG;IAChG,IAAI,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC;IACvB,kFAAkF;IAClF,OAAO,EAAE,GAAG,EAAE,CAAC;IACf,KAAK,EAAE,KAAK,CAAC;IACb,oDAAoD;IACpD,YAAY,EAAE,OAAO,CAAC;IACtB,IAAI,EAAE,KAAK,CAAC;IACZ,qEAAqE;IACrE,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK,EAAE,GAAG,SAAS,CA6CpE"}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { MinHeap } from "./min-heap.js";
|
|
2
|
+
|
|
3
|
+
/** A direction of travel: right, left, down, up. */
|
|
4
|
+
|
|
5
|
+
/** The routing grid's pitch. */
|
|
6
|
+
export const GRID = 4;
|
|
7
|
+
const TURN_COST = 14;
|
|
8
|
+
const EDGE_CROSSING_COST = 20;
|
|
9
|
+
const BORDER_CROSSING_COST = 6;
|
|
10
|
+
/** Charged for every grid step that runs parallel to a group border within HUG_DISTANCE of it. */
|
|
11
|
+
const BORDER_HUG_COST = 10;
|
|
12
|
+
const HUG_DISTANCE = 4;
|
|
13
|
+
/** A run of another edge closer than this to a grid line lies on that line. */
|
|
14
|
+
const RUN_TOLERANCE = GRID / 2;
|
|
15
|
+
const STEPS = {
|
|
16
|
+
0: [1, 0],
|
|
17
|
+
1: [-1, 0],
|
|
18
|
+
2: [0, 1],
|
|
19
|
+
3: [0, -1]
|
|
20
|
+
};
|
|
21
|
+
const HEADINGS = [0, 1, 2, 3];
|
|
22
|
+
const REVERSE = {
|
|
23
|
+
0: 1,
|
|
24
|
+
1: 0,
|
|
25
|
+
2: 3,
|
|
26
|
+
3: 2
|
|
27
|
+
};
|
|
28
|
+
function reverse(heading) {
|
|
29
|
+
return REVERSE[heading];
|
|
30
|
+
}
|
|
31
|
+
function isHorizontal(heading) {
|
|
32
|
+
return heading < 2;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The cheapest orthogonal path from `start` to `goal` on a grid of GRID
|
|
36
|
+
* pitch, or undefined when the walls leave none. The search state is a grid
|
|
37
|
+
* point together with the heading that reached it, so a turn costs the same
|
|
38
|
+
* whichever way a point was reached.
|
|
39
|
+
*/
|
|
40
|
+
export function searchRoute(search) {
|
|
41
|
+
const grid = new SearchGrid(search);
|
|
42
|
+
const start = grid.indexOf(search.start);
|
|
43
|
+
const goal = grid.indexOf(search.goal);
|
|
44
|
+
if (start === undefined || goal === undefined) return undefined;
|
|
45
|
+
if (grid.blocked[start] || grid.blocked[goal]) return undefined;
|
|
46
|
+
const states = grid.cells * 4;
|
|
47
|
+
const virtualGoal = states;
|
|
48
|
+
const cost = new Float64Array(states + 1).fill(Infinity);
|
|
49
|
+
const cameFrom = new Int32Array(states + 1).fill(-1);
|
|
50
|
+
const open = new MinHeap();
|
|
51
|
+
const startState = start * 4 + search.startHeading;
|
|
52
|
+
cost[startState] = 0;
|
|
53
|
+
open.push(startState, grid.estimate(start, goal));
|
|
54
|
+
while (open.size > 0) {
|
|
55
|
+
const state = open.pop();
|
|
56
|
+
if (state === virtualGoal) return grid.trace(cameFrom, cameFrom[state]);
|
|
57
|
+
const cell = state >> 2;
|
|
58
|
+
const heading = HEADINGS[state & 3];
|
|
59
|
+
const reached = cost[state];
|
|
60
|
+
if (cell === goal) {
|
|
61
|
+
if (heading === reverse(search.goalHeading)) continue;
|
|
62
|
+
const total = reached + (heading === search.goalHeading ? 0 : TURN_COST);
|
|
63
|
+
if (total < cost[virtualGoal]) {
|
|
64
|
+
cost[virtualGoal] = total;
|
|
65
|
+
cameFrom[virtualGoal] = state;
|
|
66
|
+
open.push(virtualGoal, total);
|
|
67
|
+
}
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
for (const next of HEADINGS) {
|
|
71
|
+
if (next === reverse(heading)) continue;
|
|
72
|
+
const step = grid.step(cell, next);
|
|
73
|
+
if (step === undefined) continue;
|
|
74
|
+
const nextState = step.cell * 4 + next;
|
|
75
|
+
const total = reached + step.cost + (next === heading ? 0 : TURN_COST);
|
|
76
|
+
if (total >= cost[nextState]) continue;
|
|
77
|
+
cost[nextState] = total;
|
|
78
|
+
cameFrom[nextState] = state;
|
|
79
|
+
open.push(nextState, total + grid.estimate(step.cell, goal));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** The grid points of one search, with what each one costs to enter. */
|
|
86
|
+
class SearchGrid {
|
|
87
|
+
#alongRunH;
|
|
88
|
+
#alongRunV;
|
|
89
|
+
/** Group borders between grid column i − 1 and column i, at each row. */
|
|
90
|
+
#bordersBeforeX;
|
|
91
|
+
#bordersBeforeY;
|
|
92
|
+
#hugH;
|
|
93
|
+
#hugV;
|
|
94
|
+
constructor(search) {
|
|
95
|
+
const {
|
|
96
|
+
window
|
|
97
|
+
} = search;
|
|
98
|
+
this.xs = axis(window.x, window.x + window.w, search.lines.x);
|
|
99
|
+
this.ys = axis(window.y, window.y + window.h, search.lines.y);
|
|
100
|
+
this.cells = this.xs.length * this.ys.length;
|
|
101
|
+
this.blocked = new Uint8Array(this.cells);
|
|
102
|
+
this.#alongRunH = new Uint8Array(this.cells);
|
|
103
|
+
this.#alongRunV = new Uint8Array(this.cells);
|
|
104
|
+
this.#bordersBeforeX = new Uint8Array(this.cells);
|
|
105
|
+
this.#bordersBeforeY = new Uint8Array(this.cells);
|
|
106
|
+
this.#hugH = new Uint8Array(this.cells);
|
|
107
|
+
this.#hugV = new Uint8Array(this.cells);
|
|
108
|
+
for (const wall of search.walls) {
|
|
109
|
+
this.#fill(this.blocked, strictlyInside(this.xs, wall.x, wall.x + wall.w), strictlyInside(this.ys, wall.y, wall.y + wall.h));
|
|
110
|
+
}
|
|
111
|
+
for (const [a, b] of search.runs) {
|
|
112
|
+
if (a.y === b.y) {
|
|
113
|
+
this.#fill(this.#alongRunH, within(this.xs, Math.min(a.x, b.x), Math.max(a.x, b.x)), near(this.ys, a.y, RUN_TOLERANCE));
|
|
114
|
+
} else {
|
|
115
|
+
this.#fill(this.#alongRunV, near(this.xs, a.x, RUN_TOLERANCE), within(this.ys, Math.min(a.y, b.y), Math.max(a.y, b.y)));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
for (const rect of search.borders) {
|
|
119
|
+
const rows = within(this.ys, rect.y, rect.y + rect.h);
|
|
120
|
+
const cols = within(this.xs, rect.x, rect.x + rect.w);
|
|
121
|
+
for (const x of [rect.x, rect.x + rect.w]) {
|
|
122
|
+
this.#fill(this.#bordersBeforeX, crossedBefore(this.xs, x), rows);
|
|
123
|
+
this.#fill(this.#hugV, near(this.xs, x, HUG_DISTANCE + 1e-6), rows);
|
|
124
|
+
}
|
|
125
|
+
for (const y of [rect.y, rect.y + rect.h]) {
|
|
126
|
+
this.#fill(this.#bordersBeforeY, cols, crossedBefore(this.ys, y));
|
|
127
|
+
this.#fill(this.#hugH, cols, near(this.ys, y, HUG_DISTANCE + 1e-6));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
indexOf(point) {
|
|
132
|
+
const i = this.xs.indexOf(point.x);
|
|
133
|
+
const j = this.ys.indexOf(point.y);
|
|
134
|
+
return i === -1 || j === -1 ? undefined : j * this.xs.length + i;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** A lower bound on the cost from `cell` to `goal`: one unit per GRID of distance. */
|
|
138
|
+
estimate(cell, goal) {
|
|
139
|
+
const width = this.xs.length;
|
|
140
|
+
return (Math.abs(this.xs[cell % width] - this.xs[goal % width]) + Math.abs(this.ys[Math.floor(cell / width)] - this.ys[Math.floor(goal / width)])) / GRID;
|
|
141
|
+
}
|
|
142
|
+
step(cell, heading) {
|
|
143
|
+
const width = this.xs.length;
|
|
144
|
+
const i = cell % width;
|
|
145
|
+
const j = Math.floor(cell / width);
|
|
146
|
+
const [di, dj] = STEPS[heading];
|
|
147
|
+
const ni = i + di;
|
|
148
|
+
const nj = j + dj;
|
|
149
|
+
if (ni < 0 || nj < 0 || ni >= width || nj >= this.ys.length) return undefined;
|
|
150
|
+
const next = nj * width + ni;
|
|
151
|
+
if (this.blocked[next]) return undefined;
|
|
152
|
+
const horizontal = isHorizontal(heading);
|
|
153
|
+
if ((horizontal ? this.#alongRunH : this.#alongRunV)[next]) return undefined;
|
|
154
|
+
const length = horizontal ? Math.abs(this.xs[ni] - this.xs[i]) : Math.abs(this.ys[nj] - this.ys[j]);
|
|
155
|
+
const crossed = horizontal ? this.#bordersBeforeX[j * width + Math.max(i, ni)] : this.#bordersBeforeY[Math.max(j, nj) * width + i];
|
|
156
|
+
const hugs = (horizontal ? this.#hugH : this.#hugV)[next] > 0;
|
|
157
|
+
const crossesRun = (horizontal ? this.#alongRunV : this.#alongRunH)[next] > 0;
|
|
158
|
+
return {
|
|
159
|
+
cell: next,
|
|
160
|
+
cost: length / GRID + crossed * BORDER_CROSSING_COST + (hugs ? BORDER_HUG_COST * length / GRID : 0) + (crossesRun ? EDGE_CROSSING_COST : 0)
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
trace(cameFrom, last) {
|
|
164
|
+
const width = this.xs.length;
|
|
165
|
+
const points = [];
|
|
166
|
+
for (let state = last; state !== -1; state = cameFrom[state]) {
|
|
167
|
+
const cell = state >> 2;
|
|
168
|
+
points.push({
|
|
169
|
+
x: this.xs[cell % width],
|
|
170
|
+
y: this.ys[Math.floor(cell / width)]
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
return points.reverse();
|
|
174
|
+
}
|
|
175
|
+
#fill(target, cols, rows) {
|
|
176
|
+
const width = this.xs.length;
|
|
177
|
+
for (const j of rows) for (const i of cols) target[j * width + i] += 1;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** Every multiple of GRID in [from, to], with the extra lines inside it, sorted and distinct. */
|
|
182
|
+
function axis(from, to, extra) {
|
|
183
|
+
const values = new Set();
|
|
184
|
+
for (let v = Math.ceil(from / GRID) * GRID; v <= to; v += GRID) values.add(v);
|
|
185
|
+
for (const v of extra) if (v >= from && v <= to) values.add(v);
|
|
186
|
+
return [...values].sort((a, b) => a - b);
|
|
187
|
+
}
|
|
188
|
+
function indicesWhere(values, keep) {
|
|
189
|
+
const indices = [];
|
|
190
|
+
for (const [index, value] of values.entries()) if (keep(value)) indices.push(index);
|
|
191
|
+
return indices;
|
|
192
|
+
}
|
|
193
|
+
function strictlyInside(values, from, to) {
|
|
194
|
+
return indicesWhere(values, v => v > from && v < to);
|
|
195
|
+
}
|
|
196
|
+
function within(values, from, to) {
|
|
197
|
+
return indicesWhere(values, v => v >= from && v <= to);
|
|
198
|
+
}
|
|
199
|
+
function near(values, at, distance) {
|
|
200
|
+
return indicesWhere(values, v => Math.abs(v - at) < distance);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/** The index i whose step from i − 1 crosses `at`. */
|
|
204
|
+
function crossedBefore(values, at) {
|
|
205
|
+
const i = values.findIndex(v => v >= at);
|
|
206
|
+
return i > 0 && values[i - 1] < at ? [i] : [];
|
|
207
|
+
}
|
|
208
|
+
//# sourceMappingURL=route-search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-search.js","names":["MinHeap","GRID","TURN_COST","EDGE_CROSSING_COST","BORDER_CROSSING_COST","BORDER_HUG_COST","HUG_DISTANCE","RUN_TOLERANCE","STEPS","HEADINGS","REVERSE","reverse","heading","isHorizontal","searchRoute","search","grid","SearchGrid","start","indexOf","goal","undefined","blocked","states","cells","virtualGoal","cost","Float64Array","fill","Infinity","cameFrom","Int32Array","open","startState","startHeading","push","estimate","size","state","pop","trace","cell","reached","goalHeading","total","next","step","nextState","alongRunH","alongRunV","bordersBeforeX","bordersBeforeY","hugH","hugV","constructor","window","xs","axis","x","w","lines","ys","y","h","length","Uint8Array","wall","walls","strictlyInside","a","b","runs","within","Math","min","max","near","rect","borders","rows","cols","crossedBefore","point","i","j","width","abs","floor","di","dj","ni","nj","horizontal","crossed","hugs","crossesRun","last","points","#fill","target","from","to","extra","values","Set","v","ceil","add","sort","indicesWhere","keep","indices","index","value","entries","at","distance","findIndex"],"sources":["../../../../src/lib/layouts/graph/route-search.ts"],"sourcesContent":["import type { Box, Point } from '../../model/diagram-ir.ts';\nimport { MinHeap } from './min-heap.ts';\n\n/** A direction of travel: right, left, down, up. */\nexport type Heading = 0 | 1 | 2 | 3;\n\n/** The routing grid's pitch. */\nexport const GRID = 4;\nconst TURN_COST = 14;\nconst EDGE_CROSSING_COST = 20;\nconst BORDER_CROSSING_COST = 6;\n/** Charged for every grid step that runs parallel to a group border within HUG_DISTANCE of it. */\nconst BORDER_HUG_COST = 10;\nconst HUG_DISTANCE = 4;\n/** A run of another edge closer than this to a grid line lies on that line. */\nconst RUN_TOLERANCE = GRID / 2;\n\nconst STEPS: Record<Heading, [number, number]> = {\n 0: [1, 0],\n 1: [-1, 0],\n 2: [0, 1],\n 3: [0, -1],\n};\nconst HEADINGS: Heading[] = [0, 1, 2, 3];\n\nconst REVERSE: Record<Heading, Heading> = { 0: 1, 1: 0, 2: 3, 3: 2 };\n\nfunction reverse(heading: Heading): Heading {\n return REVERSE[heading];\n}\n\nfunction isHorizontal(heading: Heading): boolean {\n return heading < 2;\n}\n\nexport type RouteSearch = {\n /** Only grid points inside this box are searched. */\n window: Box;\n /** Coordinates the grid holds besides every multiple of GRID: the route's own ends, slots and stubs. */\n lines: { x: number[]; y: number[] };\n /** No route passes a grid point strictly inside one of these. */\n walls: Box[];\n /** Segments of routes already drawn: a route may cross them at a cost, never run along them. */\n runs: [Point, Point][];\n /** Group rects and title bands: crossing or hugging their borders costs extra. */\n borders: Box[];\n start: Point;\n /** The heading of the stub that reaches `start`. */\n startHeading: Heading;\n goal: Point;\n /** The heading of the stub that leaves `goal` for the entry side. */\n goalHeading: Heading;\n};\n\n/**\n * The cheapest orthogonal path from `start` to `goal` on a grid of GRID\n * pitch, or undefined when the walls leave none. The search state is a grid\n * point together with the heading that reached it, so a turn costs the same\n * whichever way a point was reached.\n */\nexport function searchRoute(search: RouteSearch): Point[] | undefined {\n const grid = new SearchGrid(search);\n const start = grid.indexOf(search.start);\n const goal = grid.indexOf(search.goal);\n if (start === undefined || goal === undefined) return undefined;\n if (grid.blocked[start] || grid.blocked[goal]) return undefined;\n\n const states = grid.cells * 4;\n const virtualGoal = states;\n const cost = new Float64Array(states + 1).fill(Infinity);\n const cameFrom = new Int32Array(states + 1).fill(-1);\n const open = new MinHeap<number>();\n const startState = start * 4 + search.startHeading;\n cost[startState] = 0;\n open.push(startState, grid.estimate(start, goal));\n\n while (open.size > 0) {\n const state = open.pop()!;\n if (state === virtualGoal) return grid.trace(cameFrom, cameFrom[state]!);\n const cell = state >> 2;\n const heading = HEADINGS[state & 3]!;\n const reached = cost[state]!;\n if (cell === goal) {\n if (heading === reverse(search.goalHeading)) continue;\n const total = reached + (heading === search.goalHeading ? 0 : TURN_COST);\n if (total < cost[virtualGoal]!) {\n cost[virtualGoal] = total;\n cameFrom[virtualGoal] = state;\n open.push(virtualGoal, total);\n }\n continue;\n }\n for (const next of HEADINGS) {\n if (next === reverse(heading)) continue;\n const step = grid.step(cell, next);\n if (step === undefined) continue;\n const nextState = step.cell * 4 + next;\n const total = reached + step.cost + (next === heading ? 0 : TURN_COST);\n if (total >= cost[nextState]!) continue;\n cost[nextState] = total;\n cameFrom[nextState] = state;\n open.push(nextState, total + grid.estimate(step.cell, goal));\n }\n }\n return undefined;\n}\n\n/** The grid points of one search, with what each one costs to enter. */\nclass SearchGrid {\n readonly xs: number[];\n readonly ys: number[];\n readonly cells: number;\n readonly blocked: Uint8Array;\n readonly #alongRunH: Uint8Array;\n readonly #alongRunV: Uint8Array;\n /** Group borders between grid column i − 1 and column i, at each row. */\n readonly #bordersBeforeX: Uint8Array;\n readonly #bordersBeforeY: Uint8Array;\n readonly #hugH: Uint8Array;\n readonly #hugV: Uint8Array;\n\n constructor(search: RouteSearch) {\n const { window } = search;\n this.xs = axis(window.x, window.x + window.w, search.lines.x);\n this.ys = axis(window.y, window.y + window.h, search.lines.y);\n this.cells = this.xs.length * this.ys.length;\n this.blocked = new Uint8Array(this.cells);\n this.#alongRunH = new Uint8Array(this.cells);\n this.#alongRunV = new Uint8Array(this.cells);\n this.#bordersBeforeX = new Uint8Array(this.cells);\n this.#bordersBeforeY = new Uint8Array(this.cells);\n this.#hugH = new Uint8Array(this.cells);\n this.#hugV = new Uint8Array(this.cells);\n\n for (const wall of search.walls) {\n this.#fill(\n this.blocked,\n strictlyInside(this.xs, wall.x, wall.x + wall.w),\n strictlyInside(this.ys, wall.y, wall.y + wall.h),\n );\n }\n for (const [a, b] of search.runs) {\n if (a.y === b.y) {\n this.#fill(\n this.#alongRunH,\n within(this.xs, Math.min(a.x, b.x), Math.max(a.x, b.x)),\n near(this.ys, a.y, RUN_TOLERANCE),\n );\n } else {\n this.#fill(\n this.#alongRunV,\n near(this.xs, a.x, RUN_TOLERANCE),\n within(this.ys, Math.min(a.y, b.y), Math.max(a.y, b.y)),\n );\n }\n }\n for (const rect of search.borders) {\n const rows = within(this.ys, rect.y, rect.y + rect.h);\n const cols = within(this.xs, rect.x, rect.x + rect.w);\n for (const x of [rect.x, rect.x + rect.w]) {\n this.#fill(this.#bordersBeforeX, crossedBefore(this.xs, x), rows);\n this.#fill(this.#hugV, near(this.xs, x, HUG_DISTANCE + 1e-6), rows);\n }\n for (const y of [rect.y, rect.y + rect.h]) {\n this.#fill(this.#bordersBeforeY, cols, crossedBefore(this.ys, y));\n this.#fill(this.#hugH, cols, near(this.ys, y, HUG_DISTANCE + 1e-6));\n }\n }\n }\n\n indexOf(point: Point): number | undefined {\n const i = this.xs.indexOf(point.x);\n const j = this.ys.indexOf(point.y);\n return i === -1 || j === -1 ? undefined : j * this.xs.length + i;\n }\n\n /** A lower bound on the cost from `cell` to `goal`: one unit per GRID of distance. */\n estimate(cell: number, goal: number): number {\n const width = this.xs.length;\n return (\n (Math.abs(this.xs[cell % width]! - this.xs[goal % width]!) +\n Math.abs(\n this.ys[Math.floor(cell / width)]! -\n this.ys[Math.floor(goal / width)]!,\n )) /\n GRID\n );\n }\n\n step(\n cell: number,\n heading: Heading,\n ): { cell: number; cost: number } | undefined {\n const width = this.xs.length;\n const i = cell % width;\n const j = Math.floor(cell / width);\n const [di, dj] = STEPS[heading];\n const ni = i + di;\n const nj = j + dj;\n if (ni < 0 || nj < 0 || ni >= width || nj >= this.ys.length)\n return undefined;\n const next = nj * width + ni;\n if (this.blocked[next]) return undefined;\n const horizontal = isHorizontal(heading);\n if ((horizontal ? this.#alongRunH : this.#alongRunV)[next])\n return undefined;\n const length = horizontal\n ? Math.abs(this.xs[ni]! - this.xs[i]!)\n : Math.abs(this.ys[nj]! - this.ys[j]!);\n const crossed = horizontal\n ? this.#bordersBeforeX[j * width + Math.max(i, ni)]!\n : this.#bordersBeforeY[Math.max(j, nj) * width + i]!;\n const hugs = (horizontal ? this.#hugH : this.#hugV)[next]! > 0;\n const crossesRun =\n (horizontal ? this.#alongRunV : this.#alongRunH)[next]! > 0;\n return {\n cell: next,\n cost:\n length / GRID +\n crossed * BORDER_CROSSING_COST +\n (hugs ? (BORDER_HUG_COST * length) / GRID : 0) +\n (crossesRun ? EDGE_CROSSING_COST : 0),\n };\n }\n\n trace(cameFrom: Int32Array, last: number): Point[] {\n const width = this.xs.length;\n const points: Point[] = [];\n for (let state = last; state !== -1; state = cameFrom[state]!) {\n const cell = state >> 2;\n points.push({\n x: this.xs[cell % width]!,\n y: this.ys[Math.floor(cell / width)]!,\n });\n }\n return points.reverse();\n }\n\n #fill(target: Uint8Array, cols: number[], rows: number[]): void {\n const width = this.xs.length;\n for (const j of rows) for (const i of cols) target[j * width + i]! += 1;\n }\n}\n\n/** Every multiple of GRID in [from, to], with the extra lines inside it, sorted and distinct. */\nfunction axis(from: number, to: number, extra: number[]): number[] {\n const values = new Set<number>();\n for (let v = Math.ceil(from / GRID) * GRID; v <= to; v += GRID) values.add(v);\n for (const v of extra) if (v >= from && v <= to) values.add(v);\n return [...values].sort((a, b) => a - b);\n}\n\nfunction indicesWhere(\n values: number[],\n keep: (value: number) => boolean,\n): number[] {\n const indices: number[] = [];\n for (const [index, value] of values.entries())\n if (keep(value)) indices.push(index);\n return indices;\n}\n\nfunction strictlyInside(values: number[], from: number, to: number): number[] {\n return indicesWhere(values, (v) => v > from && v < to);\n}\n\nfunction within(values: number[], from: number, to: number): number[] {\n return indicesWhere(values, (v) => v >= from && v <= to);\n}\n\nfunction near(values: number[], at: number, distance: number): number[] {\n return indicesWhere(values, (v) => Math.abs(v - at) < distance);\n}\n\n/** The index i whose step from i − 1 crosses `at`. */\nfunction crossedBefore(values: number[], at: number): number[] {\n const i = values.findIndex((v) => v >= at);\n return i > 0 && values[i - 1]! < at ? [i] : [];\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { DiagramGraphIR } from '../../model/diagram-ir.ts';
|
|
2
|
+
import type { GridAreas } from './areas.ts';
|
|
3
|
+
import type { EdgeLayout, GroupLayout, LeaderLayout, NodeLayout } from './graph-layout-result.ts';
|
|
4
|
+
/** The routes, before the layout rounds them and draws their paths. */
|
|
5
|
+
export type RoutedGraph = {
|
|
6
|
+
edges: Omit<EdgeLayout, 'd'>[];
|
|
7
|
+
leaders: Omit<LeaderLayout, 'd'>[];
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Routes every edge and note leader orthogonally, nearest cells first, and
|
|
11
|
+
* places each edge's label and badge before the next edge routes around
|
|
12
|
+
* them. A connection with no route takes its next choice of sides, and
|
|
13
|
+
* everything routes again. It throws when a connection has no choice left,
|
|
14
|
+
* or a label has no room; it never draws a diagonal or straight line
|
|
15
|
+
* through what is in the way.
|
|
16
|
+
*/
|
|
17
|
+
export declare function routeGraph(ir: DiagramGraphIR, nodes: NodeLayout[], groups: GroupLayout[], areas: GridAreas,
|
|
18
|
+
/** How far beyond the bounding box of its two shapes a route first searches. */
|
|
19
|
+
searchMargin: number): RoutedGraph;
|
|
20
|
+
//# sourceMappingURL=route.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../src/lib/layouts/graph/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAO,cAAc,EAAS,MAAM,2BAA2B,CAAC;AAC5E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAO5C,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,YAAY,EACZ,UAAU,EACX,MAAM,0BAA0B,CAAC;AAalC,uEAAuE;AACvE,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,EAAE,CAAC;IAC/B,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,GAAG,CAAC,EAAE,CAAC;CACpC,CAAC;AAQF;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,EAAE,EAAE,cAAc,EAClB,KAAK,EAAE,UAAU,EAAE,EACnB,MAAM,EAAE,WAAW,EAAE,EACrB,KAAK,EAAE,SAAS;AAChB,gFAAgF;AAChF,YAAY,EAAE,MAAM,GACnB,WAAW,CAiBb"}
|