use crate::gui::solid_preview::diagram2d::{self, DiagramConfig, DiagramStyle};
use image::{ExtendedColorType, ImageEncoder, codecs::png::PngEncoder};
use indicatrix::geometry::{
meet_solver::SolvedTier,
stone_metrics::{SolidStatus, build_solid_mesh},
};
use indicatrix_cut_core::Design;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DiagramImage {
pub width: u32,
pub height: u32,
pub png_bytes: Vec<u8>,
}
#[must_use]
pub fn render_cut_diagram(
design: &Design,
solved: &[SolvedTier],
width: u32,
height: u32,
) -> Option<DiagramImage> {
let planes = design.planes_from_solved(solved);
let SolidStatus::Closed(mesh) = build_solid_mesh(&planes) else {
return None;
};
let config = DiagramConfig {
width,
height,
gear_teeth: design.meta.gear_teeth_abs(),
gear_reference_angle: design.meta.gear_reference_angle as f32,
symmetry_order: design.meta.symmetry_order,
mirror: design.meta.mirror,
};
let frame = diagram2d::render_diagram(&mesh, &config, &DiagramStyle::default());
let png_bytes = encode_png(frame.width, frame.height, &frame.color).ok()?;
Some(DiagramImage {
width: frame.width,
height: frame.height,
png_bytes,
})
}
fn encode_png(width: u32, height: u32, rgba: &[u8]) -> Result<Vec<u8>, String> {
let mut bytes = Vec::new();
PngEncoder::new(&mut bytes)
.write_image(rgba, width, height, ExtendedColorType::Rgba8)
.map_err(|e| e.to_string())?;
Ok(bytes)
}