use crate::artist::Patch;
use crate::core::color::Rgba;
use crate::figure::Axes;
const PIE_START_DEG: f64 = 90.0;
const PIE_EDGE_WIDTH: f64 = 1.0;
const PIE_HALF_EXTENT: f64 = 1.15;
impl Axes {
pub fn pie(&mut self, values: &[f64]) -> &mut Self {
let total: f64 = values.iter().sum();
let mut theta = PIE_START_DEG;
for &value in values {
let fraction = if total != 0.0 { value / total } else { 0.0 };
let sweep = fraction * 360.0;
let theta1 = theta;
let theta2 = theta + sweep;
let color = self.next_cycle_color();
self.add_patch(
Patch::wedge([0.0, 0.0], 1.0, theta1, theta2)
.facecolor(Some(color))
.edgecolor(Some(Rgba::WHITE))
.linewidth(PIE_EDGE_WIDTH),
);
theta = theta2;
}
self.set_aspect_equal();
self.set_axis_off();
self.set_xlim(-PIE_HALF_EXTENT, PIE_HALF_EXTENT);
self.set_ylim(-PIE_HALF_EXTENT, PIE_HALF_EXTENT);
self
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::core::Bbox;
fn wedge_span_deg(patch: &Patch) -> f64 {
let verts = patch.path().vertices();
let start = verts[1];
let end = verts[verts.len() - 2];
let a0 = start[1].atan2(start[0]).to_degrees();
let a1 = end[1].atan2(end[0]).to_degrees();
let mut span = a1 - a0;
while span < 0.0 {
span += 360.0;
}
span
}
#[test]
fn pie_creates_proportional_wedges() {
let mut ax = Axes::new(Bbox::from_extents(0.0, 0.0, 1.0, 1.0));
ax.pie(&[1.0, 2.0, 3.0]);
assert_eq!(ax.patches.len(), 3);
let spans: Vec<f64> = ax.patches.iter().map(wedge_span_deg).collect();
assert!((spans[0] - 60.0).abs() < 1e-6, "got {}", spans[0]);
assert!((spans[1] - 120.0).abs() < 1e-6, "got {}", spans[1]);
assert!((spans[2] - 180.0).abs() < 1e-6, "got {}", spans[2]);
}
#[test]
fn pie_configures_equal_aspect_and_hidden_axis() {
let mut ax = Axes::new(Bbox::from_extents(0.0, 0.0, 1.0, 1.0));
ax.pie(&[1.0, 1.0]);
assert!(ax.aspect_equal);
assert!(!ax.axis_visible);
}
}