Make the slicer generic allowing slicing into different formats
This commit is contained in:
@@ -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)
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
|
}
|
||||||
|
@@ -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 {
|
||||||
|
@@ -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;
|
||||||
|
@@ -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,
|
||||||
|
@@ -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() {
|
||||||
|
@@ -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<_>>();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user