flow_rs_core/layout/algorithms/
circular.rs

1//! Circular layout algorithm implementation
2
3use crate::error::Result;
4use crate::graph::Graph;
5use crate::layout::LayoutAlgorithm;
6use crate::types::Position;
7
8/// Circular layout algorithm
9#[derive(Debug, Clone)]
10pub struct CircularLayout {
11    pub radius: f64,
12    pub start_angle: f64,
13    pub clockwise: bool,
14}
15
16impl Default for CircularLayout {
17    fn default() -> Self {
18        Self::new()
19    }
20}
21
22impl CircularLayout {
23    /// Create a new circular layout
24    pub fn new() -> Self {
25        Self {
26            radius: 200.0,
27            start_angle: 0.0,
28            clockwise: true,
29        }
30    }
31
32    /// Set radius
33    pub fn radius(mut self, radius: f64) -> Self {
34        self.radius = radius;
35        self
36    }
37
38    /// Set start angle in radians
39    pub fn start_angle(mut self, angle: f64) -> Self {
40        self.start_angle = angle;
41        self
42    }
43
44    /// Set direction
45    pub fn clockwise(mut self, clockwise: bool) -> Self {
46        self.clockwise = clockwise;
47        self
48    }
49}
50
51impl<N, E> LayoutAlgorithm<N, E> for CircularLayout {
52    fn name(&self) -> &str {
53        "Circular"
54    }
55
56    fn apply(&mut self, graph: &mut Graph<N, E>) -> Result<()> {
57        let nodes: Vec<_> = graph.nodes_mut().collect();
58        let node_count = nodes.len();
59
60        if node_count == 0 {
61            return Ok(());
62        }
63
64        let angle_step = 2.0 * std::f64::consts::PI / node_count as f64;
65
66        for (i, node) in nodes.into_iter().enumerate() {
67            let angle = if self.clockwise {
68                self.start_angle + i as f64 * angle_step
69            } else {
70                self.start_angle - i as f64 * angle_step
71            };
72
73            let x = self.radius * angle.cos();
74            let y = self.radius * angle.sin();
75
76            node.position = Position::new(x, y);
77        }
78
79        Ok(())
80    }
81}