1use graphlib_rust::{Graph, GraphOption};
2use crate::{GraphConfig, GraphEdge, GraphEdgePoint, GraphNode};
3use crate::layout::add_border_segments::add_border_segments;
4use crate::layout::order::order;
5use crate::layout::parent_dummy_chains::parent_dummy_chains;
6use crate::layout::rank::rank;
7use crate::layout::util::{as_non_compound_graph, intersect_rect, normalize_ranks, Rect, remove_empty_ranks, transfer_node_edge_labels};
8
9pub mod acyclic;
10pub mod nesting_graph;
11pub mod util;
12pub mod rank;
13pub mod normalize;
14pub mod parent_dummy_chains;
15pub mod add_border_segments;
16pub mod order;
17pub mod coordinate_system;
18pub mod position;
19
20const DEFAULT_RANK_SEP: f32 = 50.0;
21
22pub fn layout(g: &mut Graph<GraphConfig, GraphNode, GraphEdge>) {
23 let mut layout_graph = build_layout_graph(g);
24 run_layout(&mut layout_graph);
25 update_input_graph(g, &layout_graph);
26}
27
28pub fn update_input_graph(
29 input_graph: &mut Graph<GraphConfig, GraphNode, GraphEdge>,
30 layout_graph: &Graph<GraphConfig, GraphNode, GraphEdge>,
31) {
32 for v in input_graph.nodes() {
33 let input_label_ = input_graph.node_mut(&v);
34 let layout_label = layout_graph.node(&v).unwrap();
35
36 if let Some(input_label) = input_label_ {
37 input_label.x = layout_label.x;
38 input_label.y = layout_label.y;
39
40 if layout_graph.children(&v).len() > 0 {
41 input_label.width = layout_label.width;
42 input_label.height = layout_label.height;
43 }
44 }
45 }
46
47 for e in input_graph.edges() {
48 let input_label = input_graph.edge_mut_with_obj(&e).unwrap();
49 let layout_label = layout_graph.edge_with_obj(&e).unwrap();
50
51 input_label.points = layout_label.points.clone();
52 input_label.x = layout_label.x;
53 input_label.y = layout_label.y;
54 }
55
56 input_graph.graph_mut().width = layout_graph.graph().width;
57 input_graph.graph_mut().height = layout_graph.graph().height;
58}
59
60pub fn set_graph_label_default_values(graph_label: &mut GraphConfig) {
61 if graph_label.ranksep.is_none() {
62 graph_label.ranksep = Some(50.0);
63 }
64
65 if graph_label.edgesep.is_none() {
66 graph_label.edgesep = Some(20.0);
67 }
68
69 if graph_label.nodesep.is_none() {
70 graph_label.nodesep = Some(50.0);
71 }
72
73 if graph_label.rankdir.is_none() {
74 graph_label.rankdir = Some("tb".to_string());
75 }
76
77 if graph_label.marginx.is_none() {
78 graph_label.marginx = Some(0.0);
79 }
80
81 if graph_label.marginy.is_none() {
82 graph_label.marginy = Some(0.0);
83 }
84}
85
86pub fn set_edge_label_default_values(edge_label: &mut GraphEdge) {
87 if edge_label.minlen.is_none() {
88 edge_label.minlen = Some(1.0);
89 }
90
91 if edge_label.weight.is_none() {
92 edge_label.weight = Some(1.0);
93 }
94
95 if edge_label.width.is_none() {
96 edge_label.width = Some(0.0);
97 }
98
99 if edge_label.height.is_none() {
100 edge_label.height = Some(0.0);
101 }
102
103 if edge_label.labeloffset.is_none() {
104 edge_label.labeloffset = Some(10.0);
105 }
106
107 if edge_label.labelpos.is_none() {
108 edge_label.labelpos = Some("r".to_string());
109 }
110}
111
112pub fn build_layout_graph(input_graph: &Graph<GraphConfig, GraphNode, GraphEdge>) -> Graph<GraphConfig, GraphNode, GraphEdge> {
119 let mut g: Graph<GraphConfig, GraphNode, GraphEdge> = Graph::new(Some(GraphOption {
120 directed: Some(true),
121 multigraph: Some(true),
122 compound: Some(true)
123 }));
124
125 let mut graph_label: GraphConfig = input_graph.graph().clone();
126 set_graph_label_default_values(&mut graph_label);
127 g.set_graph(graph_label);
128
129 for node_id in input_graph.nodes().iter() {
130 let _node = input_graph.node(node_id);
131 if _node.is_none() {
132 continue;
133 }
134 g.set_node(node_id.clone(), _node.cloned());
135 let _ = g.set_parent(node_id, input_graph.parent(node_id).cloned());
136 }
137
138 for edge_obj in input_graph.edges() {
139 let _edge = input_graph.edge_with_obj(&edge_obj);
140 if _edge.is_none() {
141 continue;
142 }
143 let mut edge_label = _edge.cloned().unwrap();
144 set_edge_label_default_values(&mut edge_label);
145 let _ = g.set_edge_with_obj(&edge_obj, Some(edge_label));
146 }
147
148 return g;
149}
150
151pub fn make_space_for_edge_labels(graph: &mut Graph<GraphConfig, GraphNode, GraphEdge>) {
160 let graph_config = graph.graph_mut();
161 graph_config.ranksep = Some(graph_config.ranksep.unwrap_or(DEFAULT_RANK_SEP) / 2.0);
162
163 {
165 let graph_config = graph.graph().clone();
166 let edge_objs = graph.edges();
167 for edge_obj in edge_objs.into_iter() {
168 let _edge = graph.edge_mut_with_obj(&edge_obj);
169 if _edge.is_none() {
170 continue;
171 }
172 let edge = _edge.unwrap();
173
174 let minlen = edge.minlen.unwrap_or(1.0);
175 let labelpos = edge.labelpos.clone().unwrap_or("".to_string());
176 let labeloffset = edge.labeloffset.unwrap_or(10.0);
177 let rankdir = graph_config.rankdir.clone().unwrap_or("".to_string());
178
179 edge.minlen = Some(minlen * 2.0);
180 if labelpos != "c" {
181 if rankdir == "tb" || rankdir == "bt" {
182 edge.width = Some(edge.width.unwrap_or(0.0) + labeloffset);
183 } else {
184 edge.height = Some(edge.height.unwrap_or(0.0) + labeloffset);
185 }
186 }
187 }
188 }
189}
190
191pub fn inject_edge_label_proxies(g: &mut Graph<GraphConfig, GraphNode, GraphEdge>) {
198 let edges = g.edges();
199 for e in edges.into_iter() {
200 let edge_ = g.edge_with_obj(&e);
201 if let Some(edge) = edge_ {
202 if edge.width.clone().unwrap_or(0.0) > 0.0 && edge.height.clone().unwrap_or(0.0) > 0.0 {
203 let v = g.node(&e.v);
204 let w = g.node(&e.v);
205 let v_rank = v.cloned().unwrap_or(GraphNode::default()).rank.unwrap_or(0);
206 let w_rank = w.cloned().unwrap_or(GraphNode::default()).rank.unwrap_or(0);
207 let mut label = GraphNode::default();
208 label.rank = Some((w_rank - v_rank) / 2 + v_rank);
209 util::add_dummy_node(g, "edge-proxy".to_string(), label, "_ep".to_string());
210 }
211 }
212 }
213}
214
215pub fn assign_rank_min_max(g: &mut Graph<GraphConfig, GraphNode, GraphEdge>) {
216 let mut max_rank = 0;
217 let vs = g.nodes();
218 for v in vs.iter() {
219 let node_ = g.node(v);
220 if node_.is_none() {
221 continue;
222 }
223 let node = node_.unwrap();
224 if node.border_top.is_some() {
225 let border_top = node.border_top.clone().unwrap();
226 let border_bottom = node.border_bottom.clone().unwrap();
227 let _min_rank = g.node(&border_top).cloned().unwrap().rank.unwrap_or(0);
228 let _max_rank = g.node(&border_bottom).cloned().unwrap().rank.unwrap_or(0);
229
230 let _node = g.node_mut(v).unwrap();
231 _node.min_rank = Some(_min_rank);
232 _node.max_rank = Some(_max_rank.clone());
233 max_rank = std::cmp::max(max_rank, _max_rank);
234 }
235 }
236}
237
238enum GraphElement<'a> {
239 Node(&'a GraphNode),
240 Edge(&'a GraphEdge),
241}
242
243impl<'a> GraphElement<'a> {
244 fn x(&self) -> f32 {
245 match self {
246 GraphElement::Node(node) => node.x,
247 GraphElement::Edge(edge) => edge.x,
248 }
249 }
250
251 fn y(&self) -> f32 {
252 match self {
253 GraphElement::Node(node) => node.y,
254 GraphElement::Edge(edge) => edge.y,
255 }
256 }
257
258 fn width(&self) -> f32 {
259 match self {
260 GraphElement::Node(node) => node.width,
261 GraphElement::Edge(edge) => edge.width.unwrap_or(0.0),
262 }
263 }
264
265 fn height(&self) -> f32 {
266 match self {
267 GraphElement::Node(node) => node.height,
268 GraphElement::Edge(edge) => edge.height.unwrap_or(0.0),
269 }
270 }
271}
272
273pub fn translate_graph(g: &mut Graph<GraphConfig, GraphNode, GraphEdge>) {
274 let mut min_x = f64::INFINITY as f32;
275 let mut max_x: f32 = 0.0;
276 let mut min_y = f64::INFINITY as f32;
277 let mut max_y: f32 = 0.0;
278 let mut graph_label = g.graph().clone();
279 let margin_x = graph_label.marginx.unwrap_or(0.0);
280 let margin_y = graph_label.marginy.unwrap_or(0.0);
281
282 fn get_extremes(attrs: &GraphElement, min_x: &mut f32, max_x: &mut f32, min_y: &mut f32, max_y: &mut f32) {
283 let x = attrs.x();
284 let y = attrs.y();
285 let w = attrs.width();
286 let h = attrs.height();
287 *min_x = min_x.min(x - w / 2.0);
288 *max_x = max_x.max(x + w / 2.0);
289 *min_y = min_y.min(y - h / 2.0);
290 *max_y = max_y.max(y + h / 2.0);
291 }
292
293 for v in g.nodes() {
294 get_extremes(&GraphElement::Node(g.node(&v).unwrap()), &mut min_x, &mut max_x, &mut min_y, &mut max_y);
295 }
296
297 for e in g.edges() {
298 let edge = g.edge_with_obj(&e).unwrap();
299 if edge.x != 0.0 {
300 get_extremes(&GraphElement::Edge(edge), &mut min_x, &mut max_x, &mut min_y, &mut max_y);
301 }
302 }
303
304 min_x -= margin_x;
305 min_y -= margin_y;
306
307 for v in g.nodes() {
308 let mut node = g.node_mut(&v).unwrap();
309 node.x -= min_x;
310 node.y -= min_y;
311 }
312
313 for e in g.edges() {
314 let edge = g.edge_mut_with_obj(&e).unwrap();
315 if edge.points.is_some() {
316 for p in edge.points.as_mut().unwrap() {
317 p.x -= min_x;
318 p.y -= min_y;
319 }
320 }
321 if edge.x != 0.0 {
322 edge.x = min_x;
323 }
324
325 if edge.y != 0.0 {
326 edge.y = min_y;
327 }
328 }
329
330 graph_label.width = max_x - min_x + margin_x;
331 graph_label.height = max_y - min_y + margin_y;
332
333 g.set_graph(graph_label);
334}
335
336pub fn assign_node_intersects(g: &mut Graph<GraphConfig, GraphNode, GraphEdge>) {
337 for e in g.edges() {
338 let mut edge = g.edge_mut_with_obj(&e).cloned().unwrap();
339 let node_v = g.node(&e.v).cloned().unwrap();
340 let node_w = g.node(&e.w).cloned().unwrap();
341 let (p1, p2) = if edge.points.is_none() {
342 edge.points = Some(vec![]);
343 (GraphEdgePoint {
344 x: node_w.x,
345 y: node_w.y
346 }, GraphEdgePoint {
347 x: node_v.x,
348 y: node_v.y
349 })
350 } else {
351 let points = edge.points.clone().unwrap();
352 let r1 = GraphEdgePoint {
353 x: points[0].x,
354 y: points[0].y
355 };
356
357 let r2 = GraphEdgePoint {
358 x: points[points.len() - 1].x,
359 y: points[points.len() - 1].y
360 };
361
362 (r1, r2)
363 };
364
365 let points = edge.points.as_mut().unwrap();
366 points.insert(0, intersect_rect(&Rect {
367 x: node_v.x,
368 y: node_v.y,
369 width: node_v.width,
370 height: node_v.height
371 }, &p1));
372
373 points.push(intersect_rect(&Rect {
374 x: node_w.x,
375 y: node_w.y,
376 width: node_w.width,
377 height: node_w.height
378 }, &p2));
379
380 let _ = g.set_edge_with_obj(&e, Some(edge));
381 }
382}
383
384pub fn remove_edge_label_proxies(g: &mut Graph<GraphConfig, GraphNode, GraphEdge>) {
385 let vs = g.nodes();
386 for v in vs.iter() {
387 let node = g.node(v).unwrap();
388 if node.dummy.is_some() && node.dummy.clone().unwrap() == "edge-proxy" {
389 let rank = node.rank.unwrap_or(0);
390 let graph_edge_ = g.edge_mut_with_obj(&node.e.clone().unwrap());
391 if let Some(graph_edge) = graph_edge_ {
392 graph_edge.label_rank = Some(rank);
393 }
394 g.remove_node(v);
395 }
396 }
397}
398
399pub fn fixup_edge_label_coords(g: &mut Graph<GraphConfig, GraphNode, GraphEdge>) {
400 g.edges().iter().for_each(|e| {
401 let edge = g.edge_mut_with_obj(&e.to_owned()).unwrap();
402 if edge.x != 0.0 {
403 let labelpos = edge.labelpos.clone().unwrap_or("".to_string());
404 let labeloffset = edge.labeloffset.clone().unwrap_or(0.0);
405 if labelpos == "l" || labelpos == "r" {
406 edge.width = Some(edge.width.unwrap_or(0.0) - labeloffset);
407 }
408
409 if labelpos == "l" {
410 edge.x -= edge.width.clone().unwrap_or(0.0) / 2.0 + labeloffset;
411 } else if labelpos == "r" {
412 edge.x += edge.width.clone().unwrap_or(0.0) / 2.0 + labeloffset;
413 }
414 }
415 });
416}
417
418pub fn reverse_points_for_reversed_edges(g: &mut Graph<GraphConfig, GraphNode, GraphEdge>) {
419 for e in g.edges() {
420 let edge = g.edge_mut_with_obj(&e.to_owned()).unwrap();
421 if edge.reversed.clone().unwrap_or(false) {
422 if edge.points.is_some() {
423 let points = edge.points.as_mut().unwrap();
424 points.reverse();
425 }
426 }
427 }
428}
429
430pub fn remove_border_nodes(g: &mut Graph<GraphConfig, GraphNode, GraphEdge>) {
431 for v in g.nodes() {
432 if g.children(&v).len() > 0 {
433 let mut node = g.node(&v).cloned().unwrap();
434 let t = g.node(node.border_top.as_ref().unwrap()).cloned().unwrap();
435 let b = g.node(node.border_bottom.as_ref().unwrap()).cloned().unwrap();
436 let border_left = node.border_left.clone().unwrap();
438 let mut l_keys: Vec<i32> = border_left.keys().cloned().collect();
439 l_keys.sort();
440 let border_right = node.border_right.clone().unwrap();
441 let mut r_keys: Vec<i32> = border_right.keys().cloned().collect();
442 r_keys.sort();
443 let l = g.node(border_left.get(&l_keys[l_keys.len() - 1]).unwrap()).cloned().unwrap();
444 let r = g.node(border_right.get(&r_keys[r_keys.len() - 1]).unwrap()).cloned().unwrap();
445
446 node.width = (r.x - l.x).abs();
447 node.height = (b.y - t.y).abs();
448 node.x = l.x + node.width / 2.0;
449 node.y = l.y + node.height / 2.0;
450
451 g.set_node(v.clone(), Some(node));
452 }
453 }
454
455 g.nodes().iter().for_each(|v| {
456 let node = g.node(v).unwrap();
457 if node.dummy.is_some() && node.dummy.clone().unwrap() == "border" {
458 g.remove_node(v);
459 }
460 });
461}
462
463pub fn remove_self_edges(graph: &mut Graph<GraphConfig, GraphNode, GraphEdge>) {
464 let edge_objs = graph.edges();
465 for edge_obj in edge_objs.into_iter() {
466 if edge_obj.v == edge_obj.w {
467 let edge_label = graph.edge_with_obj(&edge_obj).cloned().unwrap();
468 let node = graph.node_mut(&edge_obj.v).unwrap();
469 node.self_edges.push((edge_obj.clone(), edge_label));
470 graph.remove_edge_with_obj(&edge_obj);
471 }
472 }
473}
474
475pub fn insert_self_edges(graph: &mut Graph<GraphConfig, GraphNode, GraphEdge>) {
476 let layers = util::build_layer_matrix(graph);
477 layers.iter().for_each(|layer| {
478 let mut order_shift = 0;
479 layer.iter().enumerate().for_each(|(i, v)| {
480 let node = graph.node_mut(v).unwrap();
481 node.order = Some(i + order_shift);
482 let rank = node.rank.clone();
483
484 let self_edges = node.self_edges.clone();
485 self_edges.into_iter().for_each(|(edge, graph_edge)| {
486 let mut _graph_node = GraphNode::default();
487 _graph_node.width = graph_edge.width.clone().unwrap_or(0.0);
488 _graph_node.height = graph_edge.height.clone().unwrap_or(0.0);
489 _graph_node.rank = rank.clone();
490 order_shift += 1;
491 _graph_node.order = Some(i + order_shift);
492 _graph_node.e = Some(edge.clone());
493 _graph_node.label = Some(graph_edge.clone());
494 util::add_dummy_node(graph, "selfedge".to_string(), _graph_node, "_se".to_string());
495 });
496 });
497 })
498}
499
500pub fn position_self_edges(g: &mut Graph<GraphConfig, GraphNode, GraphEdge>) {
501 for v in g.nodes() {
502 let node = g.node(&v).cloned().unwrap();
503 if node.dummy.unwrap_or("".to_string()) == "selfedge" {
504 let self_node = g.node(&node.e.as_ref().unwrap().v).unwrap();
505 let x = self_node.x + self_node.width / 2.0;
506 let y = self_node.y;
507 let dx = node.x - x;
508 let dy = self_node.height / 2.0;
509 let mut graph_edge = node.label.clone().unwrap();
510 graph_edge.points = Some(vec![
511 GraphEdgePoint { x: x + 2.0 * dx / 3.0, y: y - dy },
512 GraphEdgePoint { x: x + 2.0 * dx / 3.0, y: y - dy },
513 GraphEdgePoint { x: x + 5.0 * dx / 6.0, y: y - dy },
514 GraphEdgePoint { x: x + dx , y },
515 GraphEdgePoint { x: x + 5.0 * dx / 6.0, y: y + dy },
516 GraphEdgePoint { x: x + 2.0 * dx / 3.0, y: y + dy }
517 ]);
518 graph_edge.x = node.x;
519 graph_edge.y = node.y;
520 let _ = g.set_edge_with_obj(&node.e.unwrap(), Some(graph_edge));
521 g.remove_node(&v);
522 }
523 }
524}
525
526pub fn run_layout(graph: &mut Graph<GraphConfig, GraphNode, GraphEdge>) {
527 make_space_for_edge_labels(graph);
528 remove_self_edges(graph);
529 acyclic::run(graph);
530 nesting_graph::run(graph);
531 let mut nc_graph: Graph<GraphConfig, GraphNode, GraphEdge> = as_non_compound_graph(graph);
533 rank(&mut nc_graph);
534 transfer_node_edge_labels(&nc_graph, graph);
535 inject_edge_label_proxies(graph);
537 remove_empty_ranks(graph);
538 nesting_graph::cleanup(graph);
539 normalize_ranks(graph);
540 assign_rank_min_max(graph);
541 remove_edge_label_proxies(graph);
542 normalize::run(graph);
543 parent_dummy_chains(graph);
544 add_border_segments(graph);
545 order(graph);
546 insert_self_edges(graph);
547 coordinate_system::adjust(graph);
548 position::position(graph);
549 position_self_edges(graph);
550 remove_border_nodes(graph);
551 normalize::undo(graph);
552 fixup_edge_label_coords(graph);
553 coordinate_system::undo(graph);
554 translate_graph(graph);
555 assign_node_intersects(graph);
556 reverse_points_for_reversed_edges(graph);
557 acyclic::undo(graph);
558}