use rustc_hash::FxHashSet as HashSet;
use crate::{
graph::{Graph, edge::Edge},
triskel::layout::{EdgeLayoutData, LayoutGraph, NodeLayoutData, layer_of},
};
pub(crate) struct SegmentInfo {
pub pvertices: HashSet<usize>,
pub qvertices: HashSet<usize>,
}
pub(crate) fn build_segments(graph: &mut LayoutGraph) -> SegmentInfo {
let mut pvertices = HashSet::default();
let mut qvertices = HashSet::default();
let mut edge_ids: Vec<usize> = graph.edges().map(|e| e.id()).collect();
edge_ids.sort_unstable();
for edge_id in edge_ids {
let edge = graph.get_edge(edge_id).unwrap();
let from = edge.from_id();
let to = edge.to_id();
let data = *edge.data();
let r0 = layer_of(graph, from);
let r1 = layer_of(graph, to);
if r1 <= r0 + 1 {
continue; }
let span_data = EdgeLayoutData {
reversed: data.reversed,
orig: data.orig,
..Default::default()
};
if r1 == r0 + 2 {
let r = graph.make_node(dummy_at(r0 + 1));
graph.remove_edge(edge_id);
graph.make_edge(from, r, span_data);
graph.make_edge(r, to, span_data);
} else {
let p = graph.make_node(dummy_at(r0 + 1));
let q = graph.make_node(dummy_at(r1 - 1));
graph.edit_edge(edge_id, p, q);
graph.make_edge(from, p, span_data);
graph.make_edge(q, to, span_data);
pvertices.insert(p);
qvertices.insert(q);
}
}
SegmentInfo {
pvertices,
qvertices,
}
}
fn dummy_at(rank: usize) -> NodeLayoutData {
NodeLayoutData {
width: 0.0,
height: 0.0,
rank: rank as i64,
is_dummy: true,
..Default::default()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::triskel::rank;
#[test]
fn long_edge_uses_two_dummies_regardless_of_span() {
let mut g = LayoutGraph::default();
let n: Vec<usize> = (0..6)
.map(|_| {
g.make_node(NodeLayoutData {
width: 10.0,
height: 10.0,
..Default::default()
})
})
.collect();
for w in n.windows(2) {
g.make_edge(w[0], w[1], EdgeLayoutData::default());
}
g.make_edge(n[0], n[5], EdgeLayoutData::default());
rank::assign_ranks(&mut g);
let info = build_segments(&mut g);
let dummies = g.nodes().filter(|node| node.is_dummy).count();
assert_eq!(dummies, 2, "span-5 long edge must use exactly 2 dummies");
assert_eq!(info.pvertices.len(), 1);
assert_eq!(info.qvertices.len(), 1);
}
}