use cadrum::{Color, DVec3, Solid};
use std::fs::File;
use std::path::{Path, PathBuf};
use crate::Result;
const SVG_MESH_TOL: f64 = 200.0;
const GRAD_START: Color = Color {
r: 0xEE as f32 / 255.0,
g: 0x78 as f32 / 255.0,
b: 0x00 as f32 / 255.0,
};
const GRAD_END: Color = Color { r: 1.0, g: 1.0, b: 1.0 };
fn lerp_color(a: Color, b: Color, t: f32) -> Color {
Color {
r: a.r + (b.r - a.r) * t,
g: a.g + (b.g - a.g) * t,
b: a.b + (b.b - a.b) * t,
}
}
pub fn run(
inputs: &[PathBuf],
extras: Vec<(String, Vec<Solid>)>,
output: &Path,
) -> Result<()> {
if inputs.is_empty() && extras.is_empty() {
return Err("compound: at least one -i input or in-memory extra is required".into());
}
let n = inputs.len() + extras.len();
let n_inputs = inputs.len();
let color = |i: usize| {
let t = if n_inputs <= 1 {
0.0
} else {
i as f32 / (n_inputs - 1) as f32
};
lerp_color(GRAD_START, GRAD_END, t)
};
let mut all: Vec<Solid> = Vec::new();
let mut i = 0usize;
for path in inputs.iter() {
let c = color(i);
let t = if n_inputs <= 1 {
0.0
} else {
i as f32 / (n_inputs - 1) as f32
};
println!(
"[{}/{}] {} t={:.3} rgb=({:.2}, {:.2}, {:.2})",
i + 1,
n,
path.display(),
t,
c.r,
c.g,
c.b
);
let solids: Vec<Solid> = cadrum::read_step(&mut File::open(path)?)
.map_err(|e| format!("read_step {}: {:?}", path.display(), e))?;
println!(" loaded {} solid(s)", solids.len());
for s in solids {
all.push(s.color(c));
}
i += 1;
}
for (label, solids) in extras {
println!(
"[{}/{}] {} (in-memory, preserve colors)",
i + 1,
n,
label
);
println!(" {} solid(s)", solids.len());
for s in solids {
all.push(s);
}
i += 1;
}
if let Some(parent) = output.parent() {
if !parent.as_os_str().is_empty() {
std::fs::create_dir_all(parent)?;
}
}
println!(
"Writing STEP: {} ({} solid(s) from {} source(s))",
output.display(),
all.len(),
n
);
cadrum::write_step(all.iter(), &mut File::create(output)?)
.map_err(|e| format!("write_step {}: {:?}", output.display(), e))?;
let svg_path = output.with_extension("svg");
println!(
"Writing SVG: {} (mesh tol = {}, rotate_x(-π/2), view=-Y)",
svg_path.display(),
SVG_MESH_TOL
);
let rotated: Vec<Solid> = all
.into_iter()
.map(|s| s.rotate_x(-std::f64::consts::FRAC_PI_2))
.collect();
let mesh = cadrum::mesh(rotated.iter(), SVG_MESH_TOL)
.map_err(|e| format!("mesh failed: {:?}", e))?;
let mut svg_file = File::create(&svg_path)
.map_err(|e| format!("create {}: {}", svg_path.display(), e))?;
mesh.write_svg(-DVec3::Y, false, true, &mut svg_file)
.map_err(|e| format!("write_svg failed: {:?}", e))?;
println!("Done.");
Ok(())
}