1use num_complex::Complex64;
2use plotters::prelude::*;
3
4pub fn generate_graph<T: AsRef<std::path::Path> + ?Sized>(
5 roots: Vec<Complex64>,
6 filename: &T,
7 dimensions: (u32, u32),
8) -> Result<(), Box<dyn std::error::Error>> {
9 let draw_area = BitMapBackend::new(filename, dimensions).into_drawing_area();
10
11 let radius = roots.first().map(|c| c.norm()).expect("No roots provided");
12 let axes_range = (radius * -1.2)..(radius * 1.2);
13
14 draw_area.fill(&WHITE)?;
15
16 let mut chart = ChartBuilder::on(&draw_area)
18 .caption(
19 format!(
20 "{} roots of {}",
21 roots.len(),
22 roots
23 .first()
24 .copied()
25 .unwrap_or_default()
26 .powi(roots.len() as i32)
27 ),
28 ("sans-serif", 50).into_font(),
29 )
30 .margin(5)
31 .x_label_area_size(30)
32 .y_label_area_size(30)
33 .build_cartesian_2d(axes_range.clone(), axes_range.clone())?;
34
35 chart.configure_mesh().draw()?;
37
38 chart.draw_series(LineSeries::new(
40 (((radius * -1.5) as i32)..=((radius * 1.5) as i32))
41 .map(|x| x as f64)
42 .map(|y| (0.0, y)),
43 BLACK,
44 ))?;
45
46 chart.draw_series(LineSeries::new(
48 (((radius * -1.5) as i32)..=((radius * 1.5) as i32))
49 .map(|x| x as f64)
50 .map(|x| (x, 0.0)),
51 BLACK,
52 ))?;
53
54 for root in roots.iter() {
56 chart.draw_series(LineSeries::new(
57 (0..=100)
58 .map(|x| x as f64 / 100.0)
59 .map(|x| (x * root.re, x * root.im)),
60 BLACK.stroke_width(2),
61 ))?;
62 }
63
64 chart.draw_series(
66 roots
67 .iter()
68 .map(|c| Circle::new((c.re, c.im), 5, BLACK.filled())),
69 )?;
70
71 chart
73 .plotting_area()
74 .draw(&Circle::new((0.0, 0.0), 5, BLACK.stroke_width(5).filled()))?;
75
76 draw_area.present()?;
78
79 Ok(())
80}
81
82#[cfg(feature = "gui")]
83pub fn show_graph(
84 roots: Vec<Complex64>,
85 dimensions: (u32, u32),
86) -> Result<(), Box<dyn std::error::Error>> {
87 use std::path::PathBuf;
88
89 use crate::app::show_image;
90
91 let path: PathBuf = [".", "temp.png"].iter().collect();
92
93 generate_graph(roots, "temp.png", dimensions)?;
94 show_image("Complex Root Graph", path, dimensions)?;
95 std::fs::remove_file("temp.png")?;
96
97 Ok(())
98}