diff --git a/bampy/src/lib.rs b/bampy/src/lib.rs index a922ddc..4fe6ede 100644 --- a/bampy/src/lib.rs +++ b/bampy/src/lib.rs @@ -1,11 +1,14 @@ +use std::iter::empty; + use approx::relative_eq; -use nalgebra::{vector, Vector3}; +use nalgebra::{vector, SimdBool, Vector3}; use serde::{Deserialize, Serialize}; +use slicer::{line::Line3, slice_rings::slice_rings}; use tsify::Tsify; use wasm_bindgen::prelude::wasm_bindgen; use crate::slicer::{ - base_slices::create_slices, mesh::Mesh, split_surface::split_surface, + base_slices::create_base_slices, mesh::Mesh, split_surface::split_surface, trace_surface::trace_surface, triangle::Triangle, FloatValue, SlicerOptions, }; @@ -36,6 +39,10 @@ pub enum Slice { #[tsify(type = "Float32Array")] position: Vec, }, + Path { + #[tsify(type = "Float32Array")] + position: Vec, + }, } #[derive(Tsify, Serialize, Deserialize)] @@ -95,12 +102,47 @@ pub fn slice( let slicer_options = SlicerOptions { layer_height }; console_log!("Creating Surfaces"); - let surfaces = split_surface(surface_triangles); + let surfaces = split_surface(surface_triangles).into_iter().map(|mesh| { + slice_rings(1, &slicer_options, &mesh) + .flat_map(|mut rings| { + /*let mut rings = rings + .into_iter() + .map(|mut ring| { + ring.points.sort_unstable_by(|a, b| { + a[0].partial_cmp(&b[0]).unwrap_or(std::cmp::Ordering::Equal) + }); + ring + }) + .collect::>();*/ + rings.sort_unstable_by(|a, b| { + a.points + .first() + .unwrap() + .partial_cmp(b.points.first().unwrap()) + .unwrap_or(std::cmp::Ordering::Equal) + }); + rings + }) + .fold(Vec::>::new(), |mut acc, mut curr| { + if acc + .last() + .zip(curr.points.first()) + .zip(curr.points.last()) + .map_or(false, |((last, start), end)| { + start.metric_distance(last) > end.metric_distance(last) + }) + { + curr.points.reverse(); + } + acc.extend(curr.points); + acc + }) + }); console_log!("Computing BVH"); let slicable = Mesh::from(slicable_triangles); console_log!("Creating Slices"); - let mut slices = create_slices(&slicer_options, &slicable); + let slices = slice_rings(2, &slicer_options, &slicable); /*console_log!("Tracing Surfaces"); let a = max_angle.tan(); @@ -114,16 +156,23 @@ pub fn slice( console_log!("Done"); SliceResult { - slices: slices - .into_iter() + slices: surfaces .map(|slice| Slice::Ring { position: slice - .points .into_iter() .flat_map(|point| [point.x as f32, point.y as f32, point.z as f32]) .collect(), }) - .chain(surfaces.into_iter().map(|surface| { + /*.chain(slices.flatten().map(|slice| { + Slice::Ring { + position: slice + .points + .into_iter() + .flat_map(|point| [point.x as f32, point.y as f32, point.z as f32]) + .collect(), + } + }))*/ + /*.chain(surfaces.into_iter().map(|surface| { Slice::Surface { position: surface .triangles @@ -143,7 +192,7 @@ pub fn slice( }) .collect(), } - })) + }))*/ .collect(), } } diff --git a/bampy/src/slicer/base_slices.rs b/bampy/src/slicer/base_slices.rs index 81828aa..637e180 100644 --- a/bampy/src/slicer/base_slices.rs +++ b/bampy/src/slicer/base_slices.rs @@ -1,28 +1,26 @@ -use super::{ - line::Line3, - mesh::Mesh, - slice_rings::{find_slice_rings, SliceRing}, - FloatValue, SlicerOptions, -}; +use super::{line::Line3, mesh::Mesh, FloatValue, SlicerOptions}; +use crate::console_log; use bvh::bvh::BvhNode; #[derive(Debug)] pub struct BaseSlice { - pub z: FloatValue, + pub d: FloatValue, pub lines: Vec, } -/// Creates base slices from the geometry, excluding surfaces. -/// The slicse are not sorted or separated into rings. -pub fn create_slices(options: &SlicerOptions, slicable: &Mesh) -> Vec { - let layer_count = (slicable.aabb.max.z / options.layer_height).floor() as usize; - let mut rings = vec![]; - let mut layer_index = 0; +/// Creates base slices from the geometry +pub fn create_base_slices<'a>( + axis: usize, + options: &'a SlicerOptions, + slicable: &'a Mesh, +) -> impl Iterator + 'a { + let layer_count = ((slicable.aabb.max[axis] - slicable.aabb.min[axis]) / options.layer_height) + .floor() as usize; - for i in 0..layer_count { - let layer = i as FloatValue * options.layer_height; + (0..layer_count).map(move |i| { + let layer = i as FloatValue * options.layer_height + slicable.aabb.min[axis]; let mut base_slice = BaseSlice { - z: layer, + d: layer, lines: vec![], }; @@ -37,12 +35,12 @@ pub fn create_slices(options: &SlicerOptions, slicable: &Mesh) -> Vec child_r_index, child_r_aabb, } => { - assert!(child_l_aabb.min.z <= child_l_aabb.max.z); - assert!(child_r_aabb.min.z <= child_r_aabb.max.z); - if layer >= child_l_aabb.min.z && layer <= child_l_aabb.max.z { + assert!(child_l_aabb.min[axis] <= child_l_aabb.max[axis]); + assert!(child_r_aabb.min[axis] <= child_r_aabb.max[axis]); + if layer >= child_l_aabb.min[axis] && layer <= child_l_aabb.max[axis] { stack.push(child_l_index); } - if layer >= child_r_aabb.min.z && layer <= child_r_aabb.max.z { + if layer >= child_r_aabb.min[axis] && layer <= child_r_aabb.max[axis] { stack.push(child_r_index); } } @@ -51,7 +49,7 @@ pub fn create_slices(options: &SlicerOptions, slicable: &Mesh) -> Vec shape_index, } => { slicable.triangles[shape_index] - .intersect_z(layer) + .intersect(layer, axis) .map(|line| { base_slice.lines.push(line); }); @@ -59,8 +57,6 @@ pub fn create_slices(options: &SlicerOptions, slicable: &Mesh) -> Vec } } - rings.append(&mut find_slice_rings(base_slice, &mut layer_index)); - } - - rings + base_slice + }) } diff --git a/bampy/src/slicer/slice_rings.rs b/bampy/src/slicer/slice_rings.rs index fff7922..7b5ab9e 100644 --- a/bampy/src/slicer/slice_rings.rs +++ b/bampy/src/slicer/slice_rings.rs @@ -3,68 +3,72 @@ use nalgebra::Vector3; use crate::console_log; -use super::{base_slices::BaseSlice, FloatValue}; +use super::{ + base_slices::{create_base_slices, BaseSlice}, + mesh::Mesh, + FloatValue, SlicerOptions, +}; #[derive(Debug)] pub struct SliceRing { - pub z: FloatValue, + pub d: FloatValue, /// The points of the ring, in clockwise order. pub points: Vec>, + pub closed: bool, } -pub fn find_slice_rings(mut slice: BaseSlice, layer_index: &mut u32) -> Vec { +pub fn slice_rings<'a>( + axis: usize, + options: &'a SlicerOptions, + slicable: &'a Mesh, +) -> impl Iterator> + 'a { + let mut layer_index = 0; + create_base_slices(axis, options, slicable) + .map(move |slice| find_slice_rings(axis, slice, &mut layer_index)) +} + +pub fn find_slice_rings( + axis: usize, + mut slice: BaseSlice, + layer_index: &mut u32, +) -> Vec { + let axis_a = (axis + 1) % 3; + let axis_b = (axis + 2) % 3; let mut rings = vec![]; while let Some(line) = slice.lines.pop() { if relative_eq!(line.start, line.end) { continue; } - let mut ring = SliceRing { - z: slice.z, - points: vec![line.start, line.end], - }; - let mut right_start = ring.points[0]; - let mut right = ring.points[1]; - let mut sum_of_edges = (right.x - right_start.x) * (right.y + right_start.y); - + let mut right = vec![line.end]; + let mut left = vec![line.start]; let mut previous_len = usize::MAX; - let mut done = false; + let mut closed = false; - while !done { + while !closed { if previous_len == slice.lines.len() { - console_log!( - "Error: Could not close ring {}, d = {}, {} items left.", - layer_index, - ring.points[0].metric_distance(&right), - slice.lines.len() - ); break; } previous_len = slice.lines.len(); slice.lines.retain_mut(|line| { - if done { + if closed { return true; } - macro_rules! add { - ( $point:expr ) => { - if !relative_eq!($point, right_start) { - right_start = right; - right = $point; - ring.points.push(right); - sum_of_edges = (right.x - right_start.x) * (right.y + right_start.y); - done = relative_eq!(ring.points[0], right); - } - }; - } + let test = |side: &mut Vec>| { + let last = side.last().unwrap(); + let s = relative_eq!(line.start, last); + let e = relative_eq!(line.end, last); + if s && !e { + side.push(line.end); + } else if !s && e { + side.push(line.start); + } + s || e + }; - let s = relative_eq!(line.start, right); - let e = relative_eq!(line.end, right); - if s && !e { - add!(line.end); - false - } else if e && !s { - add!(line.start); + if test(&mut left) || test(&mut right) { + closed = relative_eq!(left.last().unwrap(), right.last().unwrap()); false } else { true @@ -72,10 +76,21 @@ pub fn find_slice_rings(mut slice: BaseSlice, layer_index: &mut u32) -> Vec Option { + pub fn intersect(&self, value: FloatValue, axis: usize) -> Option { let mut intersection = Vec::>::with_capacity(3); let mut last = &self.c; for point in [self.a, self.b, self.c].iter() { - if relative_eq!(point.z, z) { - intersection.push(Vector3::new(point.x, point.y, z)); - } else if last.z < z && point.z > z { - let ratio = (z - last.z) / (point.z - last.z); - intersection.push(Vector3::new( - last.x + (point.x - last.x) * ratio, - last.y + (point.y - last.y) * ratio, - z, - )) - } else if last.z > z && point.z < z { - let ratio = (z - point.z) / (last.z - point.z); - intersection.push(Vector3::new( - point.x + (last.x - point.x) * ratio, - point.y + (last.y - point.y) * ratio, - z, - )) + if relative_eq!(point[axis], value) { + let mut new_point = *point; + new_point[axis] = value; + intersection.push(new_point); + } else if last[axis] < value && point[axis] > value { + let ratio = (value - last[axis]) / (point[axis] - last[axis]); + let mut new_point = last + (point - last) * ratio; + new_point[axis] = value; + intersection.push(new_point); + } else if last[axis] > value && point[axis] < value { + let ratio = (value - point[axis]) / (last[axis] - point[axis]); + let mut new_point = point + (last - point) * ratio; + new_point[axis] = value; + intersection.push(new_point); } last = point; } diff --git a/package.json b/package.json index e3f2837..6a7b3a1 100644 --- a/package.json +++ b/package.json @@ -37,4 +37,3 @@ "vite-plugin-wasm": "^3.3.0" } } - diff --git a/src/lib/components/Scene.svelte b/src/lib/components/Scene.svelte index b97d5bc..ad14255 100644 --- a/src/lib/components/Scene.svelte +++ b/src/lib/components/Scene.svelte @@ -1,6 +1,6 @@