dataviz\figure\figuretypes/
piechart.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use crate::figure::{canvas::pixelcanvas::PixelCanvas, configuration::figureconfig::FigureConfig};

/// Represents a pie chart with title, datasets, and configuration settings.
pub struct PieChart {
    /// Title of the pie chart.
    pub title: String,
    /// A collection of datasets, where each dataset contains:
    /// - A label (`String`).
    /// - A value (`f64`).
    /// - A color in RGB format (`[u8; 3]`).
    pub datasets: Vec<(String, f64, [u8; 3])>,
    /// Configuration settings for rendering the chart (e.g., fonts, colors, grid).
    pub config: FigureConfig,
}

impl PieChart {
    /// Creates a new `PieChart` instance with the specified title and configuration.
    ///
    /// # Parameters
    /// - `title`: The title of the pie chart.
    /// - `config`: The `FigureConfig` containing appearance and behavior settings.
    ///
    /// # Returns
    /// A new `PieChart` instance with no datasets.
    ///
    /// # Example
    /// ```rust
    /// use crate::figure::configuration::figureconfig::FigureConfig;
    /// use crate::figure::piechart::PieChart;
    ///
    /// let config = FigureConfig::default();
    /// let pie_chart = PieChart::new("Market Share", config);
    /// ```
    pub fn new(title: &str, config: FigureConfig) -> Self {
        Self {
            title: title.to_string(),
            datasets: Vec::new(),
            config,
        }
    }

    /// Adds a slice to the pie chart.
    ///
    /// # Parameters
    /// - `label`: The label for the slice.
    /// - `value`: The value representing the proportion of the slice.
    /// - `color`: The RGB color of the slice.
    ///
    /// # Example
    /// ```rust
    /// pie_chart.add_slice("Product A", 30.0, [255, 0, 0]);
    /// pie_chart.add_slice("Product B", 50.0, [0, 255, 0]);
    /// pie_chart.add_slice("Product C", 20.0, [0, 0, 255]);
    /// ```
    pub fn add_slice(&mut self, label: &str, value: f64, color: [u8; 3]) {
        self.datasets.push((label.to_string(), value, color));
    }

    /// Draws a slice of the pie chart on the canvas.
    ///
    /// # Parameters
    /// - `canvas`: The `PixelCanvas` to draw the slice on.
    /// - `center_x`: The x-coordinate of the center of the pie chart.
    /// - `center_y`: The y-coordinate of the center of the pie chart.
    /// - `radius`: The radius of the pie chart.
    /// - `start_angle`: The starting angle of the slice in radians.
    /// - `end_angle`: The ending angle of the slice in radians.
    /// - `color`: The RGB color of the slice.
    ///
    /// # Details
    /// This method fills a portion of the circle defined by `start_angle` and `end_angle`.
    /// It ensures that only points within the slice and the circle are drawn.
    ///
    /// # Example
    /// ```rust
    /// pie_chart.draw_slice(&mut canvas, 200, 200, 100, 0.0, 1.0, [255, 0, 0]);
    /// ```
    pub fn draw_slice(
        &self,
        canvas: &mut PixelCanvas,
        center_x: i32,
        center_y: i32,
        radius: i32,
        start_angle: f64,
        end_angle: f64,
        color: [u8; 3],
    ) {
        let start_angle_rad = start_angle;
        let end_angle_rad = end_angle;

        for y in -radius..=radius {
            for x in -radius..=radius {
                // Check if the point is within the circle
                let distance = (x * x + y * y) as f64;
                if distance <= (radius * radius) as f64 {
                    // Calculate the angle of the point
                    let angle = (y as f64).atan2(x as f64);
                    let normalized_angle = if angle < 0.0 {
                        angle + 2.0 * std::f64::consts::PI
                    } else {
                        angle
                    };

                    // Check if the angle is within the slice range
                    if normalized_angle >= start_angle_rad && normalized_angle < end_angle_rad {
                        canvas.draw_pixel((center_x + x) as u32, (center_y - y) as u32, color);
                    }
                }
            }
        }
    }
}