1#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
20pub enum Direction {
21 #[default]
23 LeftRight,
24 TopBottom,
26}
27
28#[derive(Clone, Debug, Default)]
31pub struct GraphNode {
32 pub w: f64,
33 pub h: f64,
34 pub lane: Option<usize>,
36 pub pin: (Option<f64>, Option<f64>),
38}
39
40#[derive(Clone, Debug, Default)]
44pub struct GraphEdge {
45 pub from: usize,
46 pub to: usize,
47 pub label_w: Option<f64>,
48}
49
50#[derive(Clone, Debug)]
52pub struct LayeredParams {
53 pub direction: Direction,
54 pub lanes: usize,
56 pub margin: f64,
57 pub arrow: f64,
59 pub loop_size: f64,
61 pub lane_gap: f64,
63 pub lane_head: f64,
64}
65
66impl Default for LayeredParams {
67 fn default() -> Self {
68 LayeredParams {
69 direction: Direction::LeftRight,
70 lanes: 0,
71 margin: 10.0,
72 arrow: 7.0,
73 loop_size: 16.0,
74 lane_gap: 22.0,
75 lane_head: 16.0,
76 }
77 }
78}
79
80#[derive(Clone, Debug, PartialEq)]
83pub struct PlacedNode {
84 pub cx: f64,
85 pub cy: f64,
86 pub w: f64,
87 pub h: f64,
88 pub layer: usize,
89 pub order: usize,
90}
91
92#[derive(Clone, Debug, PartialEq)]
94pub struct GraphLayout {
95 pub w: f64,
96 pub h: f64,
97 pub nodes: Vec<PlacedNode>,
98 pub edges: Vec<Vec<(f64, f64)>>,
100 pub back: Vec<bool>,
102 pub routed: Vec<bool>,
105 pub layers: usize,
106 pub bands: Vec<(usize, f64, f64, f64, f64)>,
108}
109
110pub fn layered(nodes: &[GraphNode], edges: &[GraphEdge], p: &LayeredParams) -> GraphLayout {
112 let explicit =
113 !nodes.is_empty() && nodes.iter().all(|n| n.pin.0.is_some() && n.pin.1.is_some());
114 if explicit {
115 layout_explicit(nodes, edges, p)
116 } else {
117 layout(nodes, edges, p)
118 }
119}
120
121#[derive(Clone, Debug)]
123pub struct BandedParams {
124 pub bands: usize,
127 pub margin: f64,
128 pub col_gap: f64,
130 pub row_gap: f64,
131 pub band_gap: f64,
133 pub band_head: f64,
134}
135
136impl Default for BandedParams {
137 fn default() -> Self {
138 BandedParams {
139 bands: 0,
140 margin: 10.0,
141 col_gap: 36.0,
142 row_gap: 18.0,
143 band_gap: 22.0,
144 band_head: 16.0,
145 }
146 }
147}
148
149pub fn banded(nodes: &[GraphNode], edges: &[GraphEdge], p: &BandedParams) -> GraphLayout {
163 let n = nodes.len();
164 let band = |v: usize| nodes[v].lane.unwrap_or(0).min(p.bands.saturating_sub(1));
165 let (dag, loops) = break_cycles(n, edges);
166 let mut preds: Vec<Vec<usize>> = vec![Vec::new(); n];
167 let mut succs: Vec<Vec<usize>> = vec![Vec::new(); n];
168 for &(u, v, _, _) in &dag {
169 preds[v].push(u);
170 succs[u].push(v);
171 }
172 let mut indeg: Vec<usize> = preds.iter().map(Vec::len).collect();
174 let mut done = vec![false; n];
175 let mut topo = Vec::with_capacity(n);
176 while let Some(v) = (0..n).find(|&v| !done[v] && indeg[v] == 0) {
177 done[v] = true;
178 topo.push(v);
179 for &w in &succs[v] {
180 indeg[w] -= 1;
181 }
182 }
183 let step = |u: usize, v: usize| usize::from(band(u) == band(v));
184 let below =
187 |v: usize| succs[v].is_empty() && preds[v].len() == 1 && band(preds[v][0]) == band(v);
188 let drops = |v: usize| !preds[v].is_empty() && preds[v].iter().all(|&u| band(u) != band(v));
191 let mut col = vec![0usize; n];
192 let mut used: std::collections::HashSet<(usize, usize)> = Default::default();
193 for &v in &topo {
194 col[v] = if below(v) {
195 col[preds[v][0]]
196 } else {
197 preds[v]
198 .iter()
199 .map(|&u| col[u] + step(u, v))
200 .max()
201 .unwrap_or(0)
202 };
203 if drops(v) {
204 while used.contains(&(band(v), col[v])) {
205 col[v] += 1;
206 }
207 }
208 used.insert((band(v), col[v]));
209 }
210 for &v in topo.iter().rev() {
211 if preds[v].is_empty() {
212 if let Some(m) = succs[v]
213 .iter()
214 .map(|&w| col[w].saturating_sub(step(v, w)))
215 .min()
216 {
217 col[v] = col[v].max(m);
218 }
219 }
220 }
221 let mut track = vec![0usize; n];
223 let mut taken: std::collections::HashSet<(usize, usize, usize)> = Default::default();
224 for &v in &topo {
225 let want = if below(v) {
226 track[preds[v][0]] + 1
227 } else {
228 preds[v]
229 .iter()
230 .filter(|&&u| band(u) == band(v))
231 .map(|&u| track[u])
232 .min()
233 .unwrap_or(0)
234 };
235 let mut t = want;
236 while taken.contains(&(band(v), col[v], t)) {
237 t += 1;
238 }
239 taken.insert((band(v), col[v], t));
240 track[v] = t;
241 }
242 let ncol = col.iter().max().map_or(0, |m| m + 1);
244 let mut col_w = vec![0.0f64; ncol];
245 for v in 0..n {
246 col_w[col[v]] = col_w[col[v]].max(nodes[v].w);
247 }
248 let mut col_x = vec![0.0f64; ncol];
249 let mut x = 0.0;
250 for c in 0..ncol {
251 col_x[c] = x + col_w[c] / 2.0;
252 x += col_w[c] + p.col_gap;
253 }
254 let nb = p.bands.max(1);
255 let ntr: Vec<usize> = (0..nb)
256 .map(|b| {
257 (0..n)
258 .filter(|&v| band(v) == b)
259 .map(|v| track[v] + 1)
260 .max()
261 .unwrap_or(0)
262 })
263 .collect();
264 let mut track_h: Vec<Vec<f64>> = ntr.iter().map(|&k| vec![0.0; k]).collect();
265 for v in 0..n {
266 let h = &mut track_h[band(v)][track[v]];
267 *h = h.max(nodes[v].h);
268 }
269 let lanes = p.bands > 0;
270 let mut track_y: Vec<Vec<f64>> = Vec::with_capacity(nb);
271 let mut band_span: Vec<(f64, f64)> = Vec::with_capacity(nb);
272 let mut y = 0.0;
273 for heights in &track_h {
274 if lanes {
275 y += p.band_head;
276 }
277 let top = y;
278 let mut ys = Vec::new();
279 for &h in heights {
280 ys.push(y + h / 2.0);
281 y += h + p.row_gap;
282 }
283 let bottom = if heights.is_empty() { y } else { y - p.row_gap };
284 band_span.push((top, bottom));
285 track_y.push(ys);
286 y = bottom + if lanes { p.band_gap } else { p.row_gap };
287 }
288 let mut order: Vec<usize> = (0..n).collect();
289 order.sort_by_key(|&v| (col[v], band(v), track[v], v));
290 let mut rank = vec![0usize; n];
291 for (i, &v) in order.iter().enumerate() {
292 rank[v] = i;
293 }
294 let pn: Vec<PlacedNode> = (0..n)
295 .map(|v| PlacedNode {
296 cx: col_x[col[v]],
297 cy: track_y[band(v)][track[v]],
298 w: nodes[v].w,
299 h: nodes[v].h,
300 layer: col[v],
301 order: rank[v],
302 })
303 .collect();
304 let mut edge_pts = vec![Vec::new(); edges.len()];
305 let mut back = vec![false; edges.len()];
306 let mut routed = vec![false; edges.len()];
307 let bussed = |u: usize, v: usize| band(u) != band(v) && col[u] != col[v];
314 let mut lanes_of: Vec<((usize, bool), Vec<usize>)> = Vec::new();
315 for &(_, _, k, _) in &dag {
316 let (u, v) = (edges[k].from, edges[k].to);
317 if !bussed(u, v) {
318 continue;
319 }
320 let key = (band(u), band(v) > band(u));
321 match lanes_of.iter_mut().find(|(c, _)| *c == key) {
322 Some((_, us)) if !us.contains(&u) => us.push(u),
323 Some(_) => {}
324 None => lanes_of.push((key, vec![u])),
325 }
326 }
327 const LANE: f64 = 8.0;
328 let route = |u: usize, v: usize| -> Vec<(f64, f64)> {
329 let (a, b) = (&pn[u], &pn[v]);
330 let down = band(v) > band(u);
331 let (top, bottom) = band_span[band(u)];
332 let channel = if down {
333 bottom + p.band_gap / 2.0
334 } else {
335 top - (if lanes { p.band_head } else { 0.0 }) - p.band_gap / 2.0
336 };
337 let us = lanes_of
338 .iter()
339 .find(|(c, _)| *c == (band(u), down))
340 .map_or(&[][..], |(_, us)| &us[..]);
341 let i = us.iter().position(|&x| x == u).unwrap_or(0) as f64;
342 let y = channel + (i - (us.len().max(1) - 1) as f64 / 2.0) * LANE;
343 let right = col[v] > col[u];
344 let side = |n: &PlacedNode, c: usize, r: bool| {
345 if r {
346 (
347 n.cx + n.w / 2.0,
348 col_x[c] + col_w[c] / 2.0 + p.col_gap / 2.0,
349 )
350 } else {
351 (
352 n.cx - n.w / 2.0,
353 col_x[c] - col_w[c] / 2.0 - p.col_gap / 2.0,
354 )
355 }
356 };
357 let (sx, sg) = side(a, col[u], right);
358 let sg = sg + (i - (us.len().max(1) - 1) as f64 / 2.0) * LANE;
360 let mut pts = vec![(sx, a.cy), (sg, a.cy), (sg, y)];
361 let next_band = band(v).abs_diff(band(u)) == 1;
362 let facing = if down {
363 track[v] == 0
364 } else {
365 track[v] + 1 == ntr[band(v)]
366 };
367 if next_band && facing {
368 let ey = if down {
369 b.cy - b.h / 2.0
370 } else {
371 b.cy + b.h / 2.0
372 };
373 let off = ((i - (us.len().max(1) - 1) as f64 / 2.0) * LANE)
375 .clamp(-b.w / 2.0 + 3.0, b.w / 2.0 - 3.0);
376 pts.extend([(b.cx + off, y), (b.cx + off, ey)]);
377 } else {
378 let (ex, tg) = side(b, col[v], !right);
379 pts.extend([(tg, y), (tg, b.cy), (ex, b.cy)]);
380 }
381 pts
382 };
383 for &(_, _, k, rev) in &dag {
384 let (u, v) = (edges[k].from, edges[k].to);
385 routed[k] = bussed(u, v);
386 edge_pts[k] = if bussed(u, v) {
387 route(u, v)
388 } else {
389 straight(&pn, u, v)
390 };
391 back[k] = rev;
392 }
393 for &k in &loops {
394 edge_pts[k] = self_loop(&pn[edges[k].from], true, 16.0);
395 }
396 let bands = if lanes {
397 let (x0, x1) = (-12.0, x - p.col_gap + 12.0);
398 (0..nb)
399 .filter(|&b| ntr[b] > 0)
400 .map(|b| {
401 let (top, bottom) = band_span[b];
402 (b, x0, top - p.band_head - 4.0, x1, bottom + 8.0)
403 })
404 .collect()
405 } else {
406 Vec::new()
407 };
408 let mut g = finish(pn, edge_pts, back, ncol, bands, p.margin);
409 g.routed = routed;
410 g
411}
412
413type DagEdge = (usize, usize, usize, bool);
415
416fn break_cycles(n: usize, edges: &[GraphEdge]) -> (Vec<DagEdge>, Vec<usize>) {
419 let mut out: Vec<Vec<(usize, usize)>> = vec![Vec::new(); n];
420 let mut loops = Vec::new();
421 for (k, e) in edges.iter().enumerate() {
422 if e.from == e.to {
423 loops.push(k);
424 } else {
425 out[e.from].push((e.to, k));
426 }
427 }
428 let mut state = vec![0u8; n]; let mut rev = vec![false; edges.len()];
430 for s in 0..n {
431 if state[s] != 0 {
432 continue;
433 }
434 state[s] = 1;
435 let mut stack = vec![(s, 0usize)];
436 while let Some(top) = stack.last_mut() {
437 let v = top.0;
438 if top.1 < out[v].len() {
439 let (w, k) = out[v][top.1];
440 top.1 += 1;
441 match state[w] {
442 0 => {
443 state[w] = 1;
444 stack.push((w, 0));
445 }
446 1 => rev[k] = true,
447 _ => {}
448 }
449 } else {
450 state[v] = 2;
451 stack.pop();
452 }
453 }
454 }
455 let dag = edges
456 .iter()
457 .enumerate()
458 .filter(|(_, e)| e.from != e.to)
459 .map(|(k, e)| {
460 if rev[k] {
461 (e.to, e.from, k, true)
462 } else {
463 (e.from, e.to, k, false)
464 }
465 })
466 .collect();
467 (dag, loops)
468}
469
470fn ordered(mut keys: Vec<(f64, f64, usize)>) -> Vec<usize> {
472 keys.sort_unstable_by(|a, b| {
473 a.0.total_cmp(&b.0)
474 .then(a.1.total_cmp(&b.1))
475 .then(a.2.cmp(&b.2))
476 });
477 keys.into_iter().map(|k| k.2).collect()
478}
479
480fn layer_crossings(upper: &[usize], succ: &[Vec<usize>], pos: &[usize], lower_len: usize) -> u64 {
483 let mut ends: Vec<(usize, usize)> = Vec::new();
484 for &u in upper {
485 for &v in &succ[u] {
486 ends.push((pos[u], pos[v]));
487 }
488 }
489 let lower: Vec<usize> = ordered(
490 ends.iter()
491 .enumerate()
492 .map(|(i, &(u, v))| (u as f64, v as f64, i))
493 .collect(),
494 )
495 .into_iter()
496 .map(|i| ends[i].1)
497 .collect();
498 let mut tree = vec![0u64; lower_len + 1];
499 let mut c = 0u64;
500 for (seen, &p) in lower.iter().enumerate() {
501 let mut i = p + 1;
502 let mut le = 0u64;
503 while i > 0 {
504 le += tree[i];
505 i -= 1 << i.trailing_zeros();
506 }
507 c += seen as u64 - le;
508 let mut i = p + 1;
509 while i <= lower_len {
510 tree[i] += 1;
511 i += 1 << i.trailing_zeros();
512 }
513 }
514 c
515}
516
517fn place(want: &[f64], weight: &[f64], gap: &[f64]) -> Vec<f64> {
521 let n = want.len();
522 let mut off = vec![0.0; n];
523 for i in 1..n {
524 off[i] = off[i - 1] + gap[i];
525 }
526 let mut blocks: Vec<(f64, f64, usize)> = Vec::new();
527 for i in 0..n {
528 blocks.push((weight[i] * (want[i] - off[i]), weight[i], 1));
529 while blocks.len() >= 2 {
530 let (b, a) = (blocks[blocks.len() - 1], blocks[blocks.len() - 2]);
531 if a.0 / a.1 > b.0 / b.1 {
532 blocks.pop();
533 let last = blocks.last_mut().expect("two blocks");
534 *last = (a.0 + b.0, a.1 + b.1, a.2 + b.2);
535 } else {
536 break;
537 }
538 }
539 }
540 let mut out = Vec::with_capacity(n);
541 for (s, w, c) in blocks {
542 for _ in 0..c {
543 let i = out.len();
544 out.push(s / w + off[i]);
545 }
546 }
547 out
548}
549
550fn exit(p: &PlacedNode, to: (f64, f64)) -> (f64, f64) {
552 let (dx, dy) = (to.0 - p.cx, to.1 - p.cy);
553 let sx = if dx != 0.0 {
554 p.w / 2.0 / dx.abs()
555 } else {
556 f64::INFINITY
557 };
558 let sy = if dy != 0.0 {
559 p.h / 2.0 / dy.abs()
560 } else {
561 f64::INFINITY
562 };
563 let k = sx.min(sy);
564 if k.is_finite() {
565 (p.cx + dx * k, p.cy + dy * k)
566 } else {
567 (p.cx, p.cy)
568 }
569}
570
571fn straight(pn: &[PlacedNode], u: usize, v: usize) -> Vec<(f64, f64)> {
572 let (a, b) = (&pn[u], &pn[v]);
573 vec![exit(a, (b.cx, b.cy)), exit(b, (a.cx, a.cy))]
574}
575
576fn self_loop(p: &PlacedNode, lr: bool, reach: f64) -> Vec<(f64, f64)> {
578 if lr {
579 let top = p.cy - p.h / 2.0;
580 vec![
581 (p.cx + p.w / 4.0, top),
582 (p.cx + p.w / 4.0, top - reach),
583 (p.cx - p.w / 4.0, top - reach),
584 (p.cx - p.w / 4.0, top),
585 ]
586 } else {
587 let right = p.cx + p.w / 2.0;
588 vec![
589 (right, p.cy - p.h / 4.0),
590 (right + reach, p.cy - p.h / 4.0),
591 (right + reach, p.cy + p.h / 4.0),
592 (right, p.cy + p.h / 4.0),
593 ]
594 }
595}
596
597fn layout_explicit(nodes: &[GraphNode], edges: &[GraphEdge], p: &LayeredParams) -> GraphLayout {
599 let sx = nodes.iter().map(|b| b.w).fold(0.0, f64::max) + 48.0;
600 let sy = nodes.iter().map(|b| b.h).fold(0.0, f64::max) + 24.0;
601 let pin = |v: usize| (nodes[v].pin.0.unwrap_or(0.0), nodes[v].pin.1.unwrap_or(0.0));
602 let mut xs: Vec<f64> = (0..nodes.len()).map(|v| pin(v).0).collect();
603 xs.sort_by(f64::total_cmp);
604 xs.dedup();
605 let reading = ordered((0..nodes.len()).map(|v| (pin(v).0, pin(v).1, v)).collect());
606 let mut pn: Vec<PlacedNode> = nodes
607 .iter()
608 .enumerate()
609 .map(|(v, b)| PlacedNode {
610 cx: pin(v).0 * sx,
611 cy: pin(v).1 * sy,
612 w: b.w,
613 h: b.h,
614 layer: xs.iter().position(|&x| x == pin(v).0).unwrap_or(0),
615 order: 0,
616 })
617 .collect();
618 for (i, &v) in reading.iter().enumerate() {
619 pn[v].order = i;
620 }
621 let lr = p.direction == Direction::LeftRight;
622 let pts = edges
623 .iter()
624 .map(|e| {
625 if e.from == e.to {
626 self_loop(&pn[e.from], lr, p.loop_size)
627 } else {
628 straight(&pn, e.from, e.to)
629 }
630 })
631 .collect();
632 finish(
633 pn,
634 pts,
635 vec![false; edges.len()],
636 xs.len().max(1),
637 Vec::new(),
638 p.margin,
639 )
640}
641
642fn layout(nodes: &[GraphNode], edges: &[GraphEdge], p: &LayeredParams) -> GraphLayout {
643 let n = nodes.len();
644 let (dag, loops) = break_cycles(n, edges);
645 let lr = p.direction == Direction::LeftRight;
646 let along = |b: &GraphNode| if lr { b.w } else { b.h };
647 let across = |b: &GraphNode| if lr { b.h } else { b.w };
648 let (rank_gap, node_gap) = if lr { (64.0, 20.0) } else { (48.0, 28.0) };
649 let (lane_gap, lane_head) = (p.lane_gap, p.lane_head);
650
651 let mut preds: Vec<Vec<usize>> = vec![Vec::new(); n];
654 let mut succs: Vec<Vec<usize>> = vec![Vec::new(); n];
655 for &(u, v, _, _) in &dag {
656 preds[v].push(u);
657 succs[u].push(v);
658 }
659 let mut indeg: Vec<usize> = preds.iter().map(Vec::len).collect();
660 let mut done = vec![false; n];
661 let mut topo = Vec::with_capacity(n);
662 while let Some(v) = (0..n).find(|&v| !done[v] && indeg[v] == 0) {
663 done[v] = true;
664 topo.push(v);
665 for &w in &succs[v] {
666 indeg[w] -= 1;
667 }
668 }
669 let pinned = |v: usize| {
671 nodes[v]
672 .pin
673 .0
674 .map(|x| x.round().clamp(0.0, 1000.0) as usize)
675 };
676 let any_pin = (0..n).any(|v| pinned(v).is_some());
677 let mut rank = vec![0usize; n];
678 for &v in &topo {
679 rank[v] =
680 pinned(v).unwrap_or_else(|| preds[v].iter().map(|&q| rank[q] + 1).max().unwrap_or(0));
681 }
682 for &v in topo.iter().rev() {
683 if preds[v].is_empty() && pinned(v).is_none() {
684 if let Some(m) = succs[v].iter().map(|&s| rank[s]).min() {
685 rank[v] = rank[v].max(m.saturating_sub(1));
686 }
687 }
688 }
689 let mut used = vec![false; rank.iter().max().map_or(1, |m| m + 1)];
691 for &r in &rank {
692 used[r] = true;
693 }
694 let mut renumber = vec![0usize; used.len()];
695 let mut nl = 0;
696 for (r, u) in used.iter().enumerate() {
697 renumber[r] = nl;
698 nl += usize::from(*u || any_pin);
699 }
700 for r in &mut rank {
701 *r = renumber[*r];
702 }
703 let nl = nl.max(1);
704 let (dag, free): (Vec<DagEdge>, Vec<DagEdge>) =
706 dag.into_iter().partition(|&(u, v, _, _)| rank[v] > rank[u]);
707
708 let mut vrank: Vec<usize> = rank.clone();
710 let mut vsucc: Vec<Vec<usize>> = vec![Vec::new(); n];
711 let mut vpred: Vec<Vec<usize>> = vec![Vec::new(); n];
712 let mut chains: Vec<Vec<usize>> = Vec::with_capacity(dag.len());
713 for &(u, v, _, _) in &dag {
714 let mut chain = vec![u];
715 let mut prev = u;
716 for r in rank[u] + 1..rank[v] {
717 let dmy = vrank.len();
718 vrank.push(r);
719 vsucc.push(Vec::new());
720 vpred.push(Vec::new());
721 vsucc[prev].push(dmy);
722 vpred[dmy].push(prev);
723 chain.push(dmy);
724 prev = dmy;
725 }
726 vsucc[prev].push(v);
727 vpred[v].push(prev);
728 chain.push(v);
729 chains.push(chain);
730 }
731 let nv = vrank.len();
732 let dummy = |v: usize| v >= n;
733 let mut vlane: Vec<usize> = (0..n).map(|v| nodes[v].lane.unwrap_or(p.lanes)).collect();
735 vlane.resize(nv, 0);
736 for ch in &chains {
737 for &dm in &ch[1..ch.len() - 1] {
738 vlane[dm] = vlane[ch[0]];
739 }
740 }
741 let laned = p.lanes > 0;
742
743 let mut layers: Vec<Vec<usize>> = vec![Vec::new(); nl];
745 let mut seen = vec![false; nv];
746 for s in ordered((0..nv).map(|v| (vrank[v] as f64, 0.0, v)).collect()) {
747 if seen[s] {
748 continue;
749 }
750 let mut stack = vec![s];
751 while let Some(v) = stack.pop() {
752 if seen[v] {
753 continue;
754 }
755 seen[v] = true;
756 layers[vrank[v]].push(v);
757 for &w in vsucc[v].iter().rev() {
758 if !seen[w] {
759 stack.push(w);
760 }
761 }
762 }
763 }
764 if laned {
765 for l in &mut layers {
766 *l = ordered(
767 l.iter()
768 .enumerate()
769 .map(|(i, &v)| (vlane[v] as f64, i as f64, v))
770 .collect(),
771 );
772 }
773 }
774 let mut pos = vec![0usize; nv];
775 let index = |layers: &[Vec<usize>], pos: &mut [usize]| {
776 for l in layers {
777 for (i, &v) in l.iter().enumerate() {
778 pos[v] = i;
779 }
780 }
781 };
782 index(&layers, &mut pos);
783 let crossings = |layers: &[Vec<usize>], pos: &[usize]| -> u64 {
784 (0..layers.len().saturating_sub(1))
785 .map(|r| layer_crossings(&layers[r], &vsucc, pos, layers[r + 1].len()))
786 .sum()
787 };
788
789 let mut best = layers.clone();
791 let mut best_c = crossings(&layers, &pos);
792 for it in 0..8 {
793 if best_c == 0 {
794 break;
795 }
796 let down = it % 2 == 0;
797 let rs: Vec<usize> = if down {
798 (1..nl).collect()
799 } else {
800 (0..nl.saturating_sub(1)).rev().collect()
801 };
802 for r in rs {
803 let nb = if down { &vpred } else { &vsucc };
804 let keyed: Vec<(f64, f64, usize)> = layers[r]
805 .iter()
806 .map(|&v| {
807 let k = if nb[v].is_empty() {
808 pos[v] as f64
809 } else {
810 nb[v].iter().map(|&w| pos[w] as f64).sum::<f64>() / nb[v].len() as f64
811 };
812 (vlane[v] as f64 * 1e6 + k, pos[v] as f64, v)
813 })
814 .collect();
815 layers[r] = ordered(keyed);
816 for (i, &v) in layers[r].iter().enumerate() {
817 pos[v] = i;
818 }
819 }
820 for _ in 0..4 {
821 let mut better = false;
822 for layer in layers.iter_mut() {
823 for i in 0..layer.len().saturating_sub(1) {
824 let (a, b) = (layer[i], layer[i + 1]);
825 if vlane[a] != vlane[b] {
826 continue;
827 }
828 let pair = |x: usize, y: usize| -> usize {
829 let c = |l: &[Vec<usize>]| {
830 l[x].iter()
831 .flat_map(|&q| l[y].iter().map(move |&r| (q, r)))
832 .filter(|&(q, r)| pos[q] > pos[r])
833 .count()
834 };
835 c(&vpred) + c(&vsucc)
836 };
837 if pair(b, a) < pair(a, b) {
838 layer.swap(i, i + 1);
839 pos[a] = i + 1;
840 pos[b] = i;
841 better = true;
842 }
843 }
844 }
845 if !better {
846 break;
847 }
848 }
849 let c = crossings(&layers, &pos);
850 if c < best_c {
851 best_c = c;
852 best = layers.clone();
853 }
854 }
855 let layers = best;
856 index(&layers, &mut pos);
857
858 let size = |v: usize| if dummy(v) { 0.0 } else { across(&nodes[v]) };
860 let gap_between = |a: usize, b: usize| -> f64 {
861 let g = match (dummy(a), dummy(b)) {
862 (true, true) => 8.0,
863 (false, false) => node_gap,
864 _ => 12.0,
865 };
866 let lane = if vlane[a] != vlane[b] {
867 lane_gap + lane_head
868 } else {
869 0.0
870 };
871 size(a) / 2.0 + g + lane + size(b) / 2.0
872 };
873 let mut y = vec![0.0f64; nv];
874 for l in &layers {
875 let mut at = 0.0;
876 for (i, &v) in l.iter().enumerate() {
877 if i > 0 {
878 at += gap_between(l[i - 1], v);
879 }
880 y[v] = at;
881 }
882 let mid = at / 2.0;
883 for &v in l {
884 y[v] -= mid;
885 }
886 }
887 let relax = |y: &mut Vec<f64>, r: usize, up: bool, down: bool| {
888 let l = &layers[r];
889 if l.is_empty() {
890 return;
891 }
892 let want: Vec<f64> = l
893 .iter()
894 .map(|&v| {
895 let mut nb: Vec<usize> = Vec::new();
896 if up {
897 nb.extend(&vpred[v]);
898 }
899 if down {
900 nb.extend(&vsucc[v]);
901 }
902 if nb.is_empty() {
903 y[v]
904 } else {
905 nb.iter().map(|&w| y[w]).sum::<f64>() / nb.len() as f64
906 }
907 })
908 .collect();
909 let weight: Vec<f64> = l
910 .iter()
911 .map(|&v| if dummy(v) { 2.0 } else { 1.0 })
912 .collect();
913 let gaps: Vec<f64> = (0..l.len())
914 .map(|i| {
915 if i == 0 {
916 0.0
917 } else {
918 gap_between(l[i - 1], l[i])
919 }
920 })
921 .collect();
922 for (&v, q) in l.iter().zip(place(&want, &weight, &gaps)) {
923 y[v] = q;
924 }
925 };
926 for _ in 0..6 {
927 for r in 1..nl {
928 relax(&mut y, r, true, false);
929 }
930 for r in (0..nl.saturating_sub(1)).rev() {
931 relax(&mut y, r, false, true);
932 }
933 }
934 for r in 0..nl {
935 relax(&mut y, r, true, true);
936 }
937 let mut lane_span: Vec<(f64, f64)> = Vec::new();
939 if laned {
940 let nlanes = p.lanes + 1;
941 let span = |y: &[f64], l: usize| {
942 (0..nv)
943 .filter(|&v| vlane[v] == l)
944 .map(|v| (y[v] - size(v) / 2.0, y[v] + size(v) / 2.0))
945 .fold(None, |acc: Option<(f64, f64)>, (a, b)| match acc {
946 None => Some((a, b)),
947 Some((x, z)) => Some((x.min(a), z.max(b))),
948 })
949 };
950 let mut floor: Option<f64> = None;
951 for l in 0..nlanes {
952 let Some((lo, _)) = span(&y, l) else {
953 lane_span.push((f64::NAN, f64::NAN));
954 continue;
955 };
956 if let Some(f) = floor {
957 let need = f + lane_gap + lane_head - lo;
958 if need > 0.0 {
959 for v in 0..nv {
960 if vlane[v] == l {
961 y[v] += need;
962 }
963 }
964 }
965 }
966 let (lo, hi) = span(&y, l).expect("lane has vertices");
967 lane_span.push((lo, hi));
968 floor = Some(hi);
969 }
970 }
971
972 let mut thick = vec![0.0f64; nl];
975 for v in 0..n {
976 thick[rank[v]] = thick[rank[v]].max(along(&nodes[v]));
977 }
978 let mut gap: Vec<f64> = vec![rank_gap; nl];
979 if lr {
980 for e in edges {
981 let (a, b) = (rank[e.from].min(rank[e.to]), rank[e.from].max(rank[e.to]));
982 if b != a + 1 {
983 continue;
984 }
985 if let Some(w) = e.label_w {
986 gap[a] = gap[a].max(w + 2.0 * p.arrow + 18.0);
987 }
988 }
989 }
990 let mut start_at = vec![0.0f64; nl];
991 for r in 1..nl {
992 start_at[r] = start_at[r - 1] + thick[r - 1] + gap[r - 1];
993 }
994 let centre = |r: usize| start_at[r] + thick[r] / 2.0;
995 let xy = |rk: f64, o: f64| if lr { (rk, o) } else { (o, rk) };
996
997 let mut pn: Vec<PlacedNode> = Vec::with_capacity(n);
998 for (v, b) in nodes.iter().enumerate() {
999 let (cx, cy) = xy(centre(rank[v]), y[v]);
1000 pn.push(PlacedNode {
1001 cx,
1002 cy,
1003 w: b.w,
1004 h: b.h,
1005 layer: rank[v],
1006 order: 0,
1007 });
1008 }
1009 let reading = ordered((0..n).map(|v| (rank[v] as f64, y[v], v)).collect());
1010 for (i, &v) in reading.iter().enumerate() {
1011 pn[v].order = i;
1012 }
1013
1014 let half_along = |v: usize| if lr { pn[v].w / 2.0 } else { pn[v].h / 2.0 };
1017 let side = |v: usize| if lr { pn[v].h } else { pn[v].w };
1018 let mut out_ports: Vec<Vec<usize>> = vec![Vec::new(); n];
1019 let mut in_ports: Vec<Vec<usize>> = vec![Vec::new(); n];
1020 for (c, ch) in chains.iter().enumerate() {
1021 out_ports[ch[0]].push(c);
1022 in_ports[ch[ch.len() - 1]].push(c);
1023 }
1024 for ports in &mut out_ports {
1025 *ports = ordered(ports.iter().map(|&c| (y[chains[c][1]], 0.0, c)).collect());
1026 }
1027 for ports in &mut in_ports {
1028 *ports = ordered(
1029 ports
1030 .iter()
1031 .map(|&c| (y[chains[c][chains[c].len() - 2]], 0.0, c))
1032 .collect(),
1033 );
1034 }
1035 let spread = |list: &[usize], c: usize, v: usize| -> f64 {
1036 let m = list.len();
1037 if m <= 1 {
1038 return 0.0;
1039 }
1040 let k = list.iter().position(|&x| x == c).unwrap_or(0);
1041 let span = (side(v) * 0.6).min(14.0 * (m - 1) as f64);
1042 -span / 2.0 + span * k as f64 / (m - 1) as f64
1043 };
1044 let mut edge_pts: Vec<Vec<(f64, f64)>> = vec![Vec::new(); edges.len()];
1045 let mut back = vec![false; edges.len()];
1046 for (c, ch) in chains.iter().enumerate() {
1047 let (u, v, k, rev) = dag[c];
1048 let mut pts = Vec::with_capacity(ch.len() * 2);
1049 pts.push(xy(
1050 centre(rank[u]) + half_along(u),
1051 y[u] + spread(&out_ports[u], c, u),
1052 ));
1053 for &dm in &ch[1..ch.len() - 1] {
1054 let r = vrank[dm];
1055 pts.push(xy(start_at[r], y[dm]));
1056 pts.push(xy(start_at[r] + thick[r], y[dm]));
1057 }
1058 pts.push(xy(
1059 centre(rank[v]) - half_along(v),
1060 y[v] + spread(&in_ports[v], c, v),
1061 ));
1062 if rev {
1063 pts.reverse();
1064 }
1065 edge_pts[k] = pts;
1066 back[k] = rev;
1067 }
1068 for k in loops {
1069 edge_pts[k] = self_loop(&pn[edges[k].from], lr, p.loop_size);
1070 }
1071 for &(u, v, k, rev) in &free {
1072 let mut pts = straight(&pn, u, v);
1073 if rev {
1074 pts.reverse();
1075 }
1076 edge_pts[k] = pts;
1077 back[k] = rev;
1078 }
1079 let total = start_at[nl - 1] + thick[nl - 1];
1081 let bands = lane_span
1082 .iter()
1083 .enumerate()
1084 .filter(|(l, (lo, _))| *l < p.lanes && lo.is_finite())
1085 .map(|(l, &(lo, hi))| {
1086 let (a, b) = if lr {
1087 xy(-12.0, lo - lane_head - 6.0)
1088 } else {
1089 xy(-lane_head - 10.0, lo - 8.0)
1090 };
1091 let (c, e) = xy(total + 12.0, hi + 8.0);
1092 (l, a, b, c, e)
1093 })
1094 .collect();
1095 finish(pn, edge_pts, back, nl, bands, p.margin)
1096}
1097
1098fn finish(
1100 mut pn: Vec<PlacedNode>,
1101 mut edge_pts: Vec<Vec<(f64, f64)>>,
1102 back: Vec<bool>,
1103 layers: usize,
1104 mut bands: Vec<(usize, f64, f64, f64, f64)>,
1105 margin: f64,
1106) -> GraphLayout {
1107 let (mut x0, mut y0, mut x1, mut y1) = (f64::MAX, f64::MAX, f64::MIN, f64::MIN);
1108 for q in &pn {
1109 x0 = x0.min(q.cx - q.w / 2.0);
1110 x1 = x1.max(q.cx + q.w / 2.0);
1111 y0 = y0.min(q.cy - q.h / 2.0);
1112 y1 = y1.max(q.cy + q.h / 2.0);
1113 }
1114 for &(px, py) in edge_pts.iter().flatten() {
1115 x0 = x0.min(px);
1116 x1 = x1.max(px);
1117 y0 = y0.min(py);
1118 y1 = y1.max(py);
1119 }
1120 for &(_, a, b, c, e) in &bands {
1121 x0 = x0.min(a.min(c));
1122 x1 = x1.max(a.max(c));
1123 y0 = y0.min(b.min(e));
1124 y1 = y1.max(b.max(e));
1125 }
1126 if pn.is_empty() {
1127 (x0, y0, x1, y1) = (0.0, 0.0, 0.0, 0.0);
1128 }
1129 let r = |v: f64| (v * 2.0).round() / 2.0;
1130 let (dx, dy) = (margin - x0, margin - y0);
1131 for q in &mut pn {
1132 q.cx = r(q.cx + dx);
1133 q.cy = r(q.cy + dy);
1134 }
1135 for pts in &mut edge_pts {
1136 for pt in pts.iter_mut() {
1137 *pt = (r(pt.0 + dx), r(pt.1 + dy));
1138 }
1139 }
1140 for b in &mut bands {
1141 *b = (b.0, r(b.1 + dx), r(b.2 + dy), r(b.3 + dx), r(b.4 + dy));
1142 }
1143 GraphLayout {
1144 w: r(x1 - x0 + 2.0 * margin),
1145 h: r(y1 - y0 + 2.0 * margin),
1146 routed: vec![false; edge_pts.len()],
1147 nodes: pn,
1148 edges: edge_pts,
1149 back,
1150 layers,
1151 bands,
1152 }
1153}
1154
1155#[cfg(test)]
1156mod tests {
1157 use super::*;
1158
1159 fn node(w: f64, h: f64) -> GraphNode {
1160 GraphNode {
1161 w,
1162 h,
1163 ..Default::default()
1164 }
1165 }
1166 fn edge(from: usize, to: usize) -> GraphEdge {
1167 GraphEdge {
1168 from,
1169 to,
1170 label_w: None,
1171 }
1172 }
1173
1174 #[test]
1175 fn a_chain_runs_left_to_right_in_layers() {
1176 let l = layered(
1177 &[node(100.0, 40.0), node(100.0, 40.0), node(100.0, 40.0)],
1178 &[edge(0, 1), edge(1, 2)],
1179 &LayeredParams::default(),
1180 );
1181 assert_eq!(l.layers, 3);
1182 assert!(l.nodes[0].cx < l.nodes[1].cx && l.nodes[1].cx < l.nodes[2].cx);
1183 assert_eq!(l.nodes[0].cy, l.nodes[1].cy);
1184 assert_eq!(l.edges[0][0].0, l.nodes[0].cx + 50.0);
1186 assert_eq!(l.edges[0].last().unwrap().0, l.nodes[1].cx - 50.0);
1187 }
1188
1189 #[test]
1190 fn a_cycle_is_broken_and_marked_back() {
1191 let l = layered(
1192 &[node(80.0, 30.0), node(80.0, 30.0)],
1193 &[edge(0, 1), edge(1, 0)],
1194 &LayeredParams::default(),
1195 );
1196 assert_eq!(l.back, vec![false, true]);
1197 assert_eq!(l.layers, 2);
1198 }
1199
1200 #[test]
1201 fn crossings_are_removed_where_possible() {
1202 let ns = vec![node(60.0, 30.0); 4];
1204 let l = layered(&ns, &[edge(0, 3), edge(1, 2)], &LayeredParams::default());
1205 let (a, b, c, d) = (&l.nodes[0], &l.nodes[1], &l.nodes[2], &l.nodes[3]);
1206 assert_eq!(a.cy < b.cy, d.cy < c.cy, "{a:?} {b:?} {c:?} {d:?}");
1207 }
1208
1209 #[test]
1210 fn pins_and_the_explicit_grid() {
1211 let mut ns = vec![node(60.0, 30.0); 3];
1212 ns[2].pin.0 = Some(3.0);
1213 let l = layered(&ns, &[edge(0, 1)], &LayeredParams::default());
1214 assert_eq!(l.nodes[2].layer, 3, "a pinned layer keeps its number");
1215 let grid: Vec<GraphNode> = (0..4)
1216 .map(|i| GraphNode {
1217 w: 60.0,
1218 h: 30.0,
1219 pin: (Some((i % 2) as f64), Some((i / 2) as f64)),
1220 ..Default::default()
1221 })
1222 .collect();
1223 let g = layered(&grid, &[edge(0, 3)], &LayeredParams::default());
1224 assert_eq!(g.layers, 2);
1225 assert_eq!(g.nodes[0].cy, g.nodes[1].cy);
1226 assert_eq!(g.edges[0].len(), 2, "straight");
1227 }
1228
1229 #[test]
1230 fn lanes_become_bands_and_top_bottom_swaps_the_axes() {
1231 let mut ns = vec![node(60.0, 30.0); 2];
1232 ns[0].lane = Some(0);
1233 ns[1].lane = Some(1);
1234 let l = layered(
1235 &ns,
1236 &[edge(0, 1)],
1237 &LayeredParams {
1238 lanes: 2,
1239 ..Default::default()
1240 },
1241 );
1242 assert_eq!(l.bands.len(), 2);
1243 let tb = layered(
1244 &ns[..1],
1245 &[],
1246 &LayeredParams {
1247 direction: Direction::TopBottom,
1248 ..Default::default()
1249 },
1250 );
1251 assert_eq!(tb.nodes.len(), 1);
1252 let t = layered(
1253 &[node(60.0, 30.0), node(60.0, 30.0)],
1254 &[edge(0, 1)],
1255 &LayeredParams {
1256 direction: Direction::TopBottom,
1257 ..Default::default()
1258 },
1259 );
1260 assert!(t.nodes[0].cy < t.nodes[1].cy && t.nodes[0].cx == t.nodes[1].cx);
1261 }
1262
1263 #[test]
1264 fn edge_cases_loops_labels_ports_lanes_and_empty() {
1265 let p = LayeredParams::default();
1266 let empty = layered(&[], &[], &p);
1267 assert!(empty.nodes.is_empty() && empty.layers == 1);
1268 for dir in [Direction::LeftRight, Direction::TopBottom] {
1270 let q = LayeredParams {
1271 direction: dir,
1272 ..Default::default()
1273 };
1274 let l = layered(
1275 &[node(60.0, 30.0), node(60.0, 30.0)],
1276 &[edge(0, 0), edge(0, 1)],
1277 &q,
1278 );
1279 assert_eq!(l.edges[0].len(), 4, "a self-loop");
1280 let g: Vec<GraphNode> = (0..2)
1281 .map(|i| GraphNode {
1282 w: 60.0,
1283 h: 30.0,
1284 pin: (Some(i as f64), Some(0.0)),
1285 ..Default::default()
1286 })
1287 .collect();
1288 let gl = layered(&g, &[edge(1, 1), edge(0, 1)], &q);
1289 assert_eq!(gl.edges[0].len(), 4);
1290 }
1291 let ns = vec![node(60.0, 30.0); 4];
1293 let plain = layered(
1294 &ns,
1295 &[edge(0, 1), edge(1, 2), edge(0, 2), edge(0, 3), edge(2, 3)],
1296 &p,
1297 );
1298 let labelled = layered(
1299 &ns,
1300 &[
1301 GraphEdge {
1302 from: 0,
1303 to: 1,
1304 label_w: Some(300.0),
1305 },
1306 edge(1, 2),
1307 edge(0, 2),
1308 edge(0, 3),
1309 edge(2, 3),
1310 ],
1311 &p,
1312 );
1313 assert!(
1314 labelled.nodes[1].cx - labelled.nodes[0].cx > plain.nodes[1].cx - plain.nodes[0].cx
1315 );
1316 assert!(
1317 plain.edges[3].len() > 2,
1318 "a long edge bends through its dummies"
1319 );
1320 let starts: Vec<f64> = [0, 2, 3].iter().map(|&k| plain.edges[k][0].1).collect();
1322 assert!(starts.windows(2).any(|w| w[0] != w[1]), "{starts:?}");
1323 let mut pn = vec![node(60.0, 30.0); 3];
1325 pn[0].pin.0 = Some(2.0);
1326 pn[1].pin.0 = Some(0.0);
1327 let back = layered(&pn, &[edge(0, 1), edge(1, 2)], &p);
1328 assert_eq!(back.edges[0].len(), 2);
1329 let mut lanes = vec![node(60.0, 30.0); 5];
1331 for (i, n) in lanes.iter_mut().enumerate().take(4) {
1332 n.lane = Some(i % 2);
1333 }
1334 let q = LayeredParams {
1335 direction: Direction::TopBottom,
1336 lanes: 2,
1337 ..Default::default()
1338 };
1339 let tb = layered(
1340 &lanes,
1341 &[edge(0, 3), edge(1, 2), edge(2, 4), edge(3, 4)],
1342 &q,
1343 );
1344 assert_eq!(tb.bands.len(), 2);
1345 assert!(tb.bands.iter().all(|b| b.3 > b.1 && b.4 > b.2));
1346 }
1347
1348 #[test]
1351 fn banded_fans_out_drops_and_hangs_leaves_below() {
1352 let node = |lane| GraphNode {
1354 w: 40.0,
1355 h: 20.0,
1356 lane: Some(lane),
1357 ..Default::default()
1358 };
1359 let mut nodes = vec![node(0)];
1360 nodes.extend((0..3).map(|_| node(1)));
1361 nodes.extend((0..3).map(|_| node(1)));
1362 let edge = |from, to| GraphEdge {
1363 from,
1364 to,
1365 label_w: None,
1366 };
1367 let mut edges = Vec::new();
1368 for i in 0..3 {
1369 edges.push(edge(0, 1 + i));
1370 edges.push(edge(1 + i, 4 + i));
1371 }
1372 let l = banded(
1373 &nodes,
1374 &edges,
1375 &BandedParams {
1376 bands: 2,
1377 ..Default::default()
1378 },
1379 );
1380 let cx: Vec<f64> = (1..=3).map(|i| l.nodes[i].cx).collect();
1381 assert!(cx[0] < cx[1] && cx[1] < cx[2], "fanned out: {cx:?}");
1382 for i in 0..3 {
1383 let (f, y) = (&l.nodes[1 + i], &l.nodes[4 + i]);
1384 assert_eq!(f.cx, y.cx, "y{i} under its factor");
1385 assert!(y.cy > f.cy);
1386 }
1387 }
1388}