Make the slicer generic allowing slicing into different formats

This commit is contained in:
Connor Slade
2024-07-03 12:59:59 -04:00
parent 5fdf616fbe
commit 3fae064c63
7 changed files with 78 additions and 57 deletions

View File

@@ -39,8 +39,8 @@ impl Image {
let half_kernel_size = kernel_size / 2; let half_kernel_size = kernel_size / 2;
let mut kernel = vec![0.0; kernel_size]; let mut kernel = vec![0.0; kernel_size];
for x in 0..kernel_size { for (i, e) in kernel.iter_mut().enumerate().take(kernel_size) {
kernel[x] = gaussian((x - half_kernel_size) as f32, sigma); *e = gaussian((i - half_kernel_size) as f32, sigma);
} }
// Blur image horizontally // Blur image horizontally
@@ -104,6 +104,6 @@ impl Image {
} }
fn gaussian(x: f32, sigma: f32) -> f32 { fn gaussian(x: f32, sigma: f32) -> f32 {
const ROOT_TWO_PI: f32 = 2.50662827463100050242; const ROOT_TWO_PI: f32 = 2.506_628_3;
(x.powi(2) / (2.0 * sigma.powi(2))).exp() / (sigma * ROOT_TWO_PI) (x.powi(2) / (2.0 * sigma.powi(2))).exp() / (sigma * ROOT_TWO_PI)
} }

View File

@@ -1,7 +1,7 @@
use crate::{config::SliceConfig, image::Image}; use crate::config::SliceConfig;
pub struct SliceResult<'a> { pub struct SliceResult<'a, Layer> {
pub layers: Vec<Image>, pub layers: Vec<Layer>,
pub slice_config: &'a SliceConfig, pub slice_config: &'a SliceConfig,
} }
@@ -9,3 +9,11 @@ pub struct Run {
pub length: u64, pub length: u64,
pub value: u8, pub value: u8,
} }
pub trait EncodableLayer {
type Output: Send;
fn new() -> Self;
fn add_run(&mut self, length: u64, value: u8);
fn finish(self, layer: usize, config: &SliceConfig) -> Self::Output;
}

View File

@@ -1,6 +1,9 @@
use common::misc::Run; use common::{
config::SliceConfig,
misc::{EncodableLayer, Run},
};
use crate::layer_content::calculate_checksum; use crate::{layer_content::calculate_checksum, LayerContent};
pub struct LayerEncoder { pub struct LayerEncoder {
data: Vec<u8>, data: Vec<u8>,
@@ -102,6 +105,41 @@ impl LayerEncoder {
} }
} }
impl EncodableLayer for LayerEncoder {
type Output = LayerContent;
fn new() -> Self {
Self::new()
}
fn add_run(&mut self, length: u64, value: u8) {
self.add_run(length, value);
}
fn finish(self, layer: usize, slice_config: &SliceConfig) -> Self::Output {
let (data, checksum) = self.finish();
let layer_exposure = if (layer as u32) < slice_config.first_layers {
&slice_config.first_exposure_config
} else {
&slice_config.exposure_config
};
LayerContent {
data,
checksum,
layer_position_z: slice_config.slice_height * (layer + 1) as f32,
layer_exposure_time: layer_exposure.exposure_time,
lift_distance: layer_exposure.lift_distance,
lift_speed: layer_exposure.lift_speed,
retract_distance: layer_exposure.retract_distance,
retract_speed: layer_exposure.retract_speed,
pause_position_z: slice_config.platform_size.z,
..Default::default()
}
}
}
impl<'a> LayerDecoder<'a> { impl<'a> LayerDecoder<'a> {
pub fn new(data: &'a [u8]) -> Self { pub fn new(data: &'a [u8]) -> Self {
Self { Self {

View File

@@ -5,7 +5,7 @@ use common::{
serde::{Deserializer, Serializer}, serde::{Deserializer, Serializer},
}; };
use crate::{HeaderInfo, LayerContent, LayerEncoder, ENDING_STRING}; use crate::{HeaderInfo, LayerContent, ENDING_STRING};
pub struct File { pub struct File {
pub header: HeaderInfo, pub header: HeaderInfo,
@@ -17,41 +17,11 @@ impl File {
Self { header, layers } Self { header, layers }
} }
pub fn from_slice_result(result: SliceResult) -> Self { pub fn from_slice_result(result: SliceResult<LayerContent>) -> Self {
let slice_config = result.slice_config; let SliceResult {
let layers = result layers,
.layers slice_config,
.into_iter() } = result;
.enumerate()
.map(|(idx, layer)| {
let mut encoder = LayerEncoder::new();
for run in layer.runs() {
encoder.add_run(run.length, run.value);
}
let (data, checksum) = encoder.finish();
let layer_exposure = if (idx as u32) < slice_config.first_layers {
&slice_config.first_exposure_config
} else {
&slice_config.exposure_config
};
LayerContent {
data,
checksum,
layer_position_z: slice_config.slice_height * (idx + 1) as f32,
layer_exposure_time: layer_exposure.exposure_time,
lift_distance: layer_exposure.lift_distance,
lift_speed: layer_exposure.lift_speed,
retract_distance: layer_exposure.retract_distance,
retract_speed: layer_exposure.retract_speed,
pause_position_z: slice_config.platform_size.z,
..Default::default()
}
})
.collect::<Vec<_>>();
let layer_time = slice_config.exposure_config.exposure_time let layer_time = slice_config.exposure_config.exposure_time
+ slice_config.exposure_config.lift_distance / slice_config.exposure_config.lift_speed; + slice_config.exposure_config.lift_distance / slice_config.exposure_config.lift_speed;

View File

@@ -21,7 +21,7 @@ use crate::{
windows::{self, Windows}, windows::{self, Windows},
}; };
use common::config::{ExposureConfig, SliceConfig}; use common::config::{ExposureConfig, SliceConfig};
use goo_format::File as GooFile; use goo_format::{File as GooFile, LayerEncoder};
pub struct App { pub struct App {
pub camera: Camera, pub camera: Camera,
@@ -84,7 +84,7 @@ impl App {
self.slice_progress = Some(slicer.progress()); self.slice_progress = Some(slicer.progress());
thread::spawn(clone!([{ self.slice_result } as slice_result], move || { thread::spawn(clone!([{ self.slice_result } as slice_result], move || {
let goo = GooFile::from_slice_result(slicer.slice()); let goo = GooFile::from_slice_result(slicer.slice::<LayerEncoder>());
slice_result.lock().unwrap().replace(SliceResult { slice_result.lock().unwrap().replace(SliceResult {
goo, goo,
slice_preview_layer: 0, slice_preview_layer: 0,

View File

@@ -12,7 +12,7 @@ use common::{
config::{ExposureConfig, SliceConfig}, config::{ExposureConfig, SliceConfig},
serde::DynamicSerializer, serde::DynamicSerializer,
}; };
use goo_format::File as GooFile; use goo_format::{File as GooFile, LayerEncoder};
use slicer::{mesh::load_mesh, slicer::Slicer, Pos}; use slicer::{mesh::load_mesh, slicer::Slicer, Pos};
fn main() -> Result<()> { fn main() -> Result<()> {
@@ -66,7 +66,7 @@ fn main() -> Result<()> {
let slicer = Slicer::new(slice_config.clone(), mesh); let slicer = Slicer::new(slice_config.clone(), mesh);
let progress = slicer.progress(); let progress = slicer.progress();
let goo = thread::spawn(move || GooFile::from_slice_result(slicer.slice())); let goo = thread::spawn(move || GooFile::from_slice_result(slicer.slice::<LayerEncoder>()));
let mut completed = 0; let mut completed = 0;
while completed < progress.total() { while completed < progress.total() {

View File

@@ -6,7 +6,10 @@ use std::{
}, },
}; };
use common::{config::SliceConfig, image::Image, misc::SliceResult}; use common::{
config::SliceConfig,
misc::{EncodableLayer, SliceResult},
};
use ordered_float::OrderedFloat; use ordered_float::OrderedFloat;
use rayon::iter::{IntoParallelIterator, ParallelIterator}; use rayon::iter::{IntoParallelIterator, ParallelIterator};
@@ -58,7 +61,7 @@ impl Slicer {
self.progress.clone() self.progress.clone()
} }
pub fn slice(&self) -> SliceResult { pub fn slice<Layer: EncodableLayer>(&self) -> SliceResult<Layer::Output> {
let (slice_config, model) = (&self.slice_config, &self.model); let (slice_config, model) = (&self.slice_config, &self.model);
let layers = (0..self.progress.total) let layers = (0..self.progress.total)
.into_par_iter() .into_par_iter()
@@ -98,23 +101,25 @@ impl Slicer {
} }
} }
let mut image = Image::blank( // let mut image = Image::blank(
self.slice_config.platform_resolution.x as usize, // self.slice_config.platform_resolution.x as usize,
self.slice_config.platform_resolution.y as usize, // self.slice_config.platform_resolution.y as usize,
); // );
let mut encoder = Layer::new();
let mut last = 0; let mut last = 0;
for (start, end) in out { for (start, end) in out {
if start > last { if start > last {
image.add_run((start - last) as usize, 0); encoder.add_run(start - last, 0);
} }
assert!(end >= start, "End precedes start in layer {layer}"); assert!(end >= start, "End precedes start in layer {layer}");
image.add_run((end - start) as usize, 255); encoder.add_run(end - start, 255);
last = end; last = end;
} }
image encoder.finish(layer as usize, slice_config)
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();