mirror of
https://github.com/Theaninova/Bampy.git
synced 2025-12-11 03:56:17 +00:00
feat: testing
This commit is contained in:
177
;
Normal file
177
;
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
use super::{
|
||||||
|
axis::Axis,
|
||||||
|
base_slices::BaseSlice,
|
||||||
|
line::Line3,
|
||||||
|
slice_path::{SlicePath, SurfacePathIterator},
|
||||||
|
triangle::Triangle,
|
||||||
|
FloatValue,
|
||||||
|
};
|
||||||
|
use bvh::{
|
||||||
|
aabb::Aabb,
|
||||||
|
bvh::{Bvh, BvhNode},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Mesh {
|
||||||
|
pub aabb: Aabb<FloatValue, 3>,
|
||||||
|
pub bvh: Bvh<FloatValue, 3>,
|
||||||
|
pub triangles: Vec<Triangle>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vec<Triangle>> for Mesh {
|
||||||
|
fn from(mut triangles: Vec<Triangle>) -> Self {
|
||||||
|
Self {
|
||||||
|
aabb: triangles
|
||||||
|
.get(0)
|
||||||
|
.map(|triangle| {
|
||||||
|
let mut aabb = triangle.aabb;
|
||||||
|
for triangle in triangles.iter().skip(1) {
|
||||||
|
aabb.join_mut(&triangle.aabb);
|
||||||
|
}
|
||||||
|
aabb
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| Aabb::empty()),
|
||||||
|
bvh: Bvh::build(&mut triangles),
|
||||||
|
triangles,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mesh {
|
||||||
|
pub fn slice_paths<'a>(
|
||||||
|
self: &'a Mesh,
|
||||||
|
axis: Axis,
|
||||||
|
slice_height: FloatValue,
|
||||||
|
) -> impl Iterator<Item = Vec<SlicePath>> + 'a {
|
||||||
|
self.slice_base_slices(axis, slice_height)
|
||||||
|
.map(|slice| slice.find_paths())
|
||||||
|
.filter(|paths| !paths.is_empty())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn slice_surface(&self, axis: Axis, nozzle_width: FloatValue) -> SurfacePathIterator {
|
||||||
|
SurfacePathIterator::new(self, axis, nozzle_width)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn slice_base_slices<'a>(
|
||||||
|
self: &'a Mesh,
|
||||||
|
axis: Axis,
|
||||||
|
slice_height: FloatValue,
|
||||||
|
) -> impl Iterator<Item = BaseSlice> + 'a {
|
||||||
|
let layer_count = ((self.aabb.max[axis as usize] - self.aabb.min[axis as usize])
|
||||||
|
/ slice_height)
|
||||||
|
.floor() as usize;
|
||||||
|
|
||||||
|
(0..layer_count).map(move |i| {
|
||||||
|
let layer = i as FloatValue * slice_height + self.aabb.min[axis as usize];
|
||||||
|
let mut base_slice = BaseSlice {
|
||||||
|
i,
|
||||||
|
d: layer,
|
||||||
|
axis,
|
||||||
|
lines: vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut stack = Vec::<usize>::with_capacity(self.bvh.nodes.len());
|
||||||
|
stack.push(0);
|
||||||
|
while let Some(i) = stack.pop() {
|
||||||
|
match self.bvh.nodes[i] {
|
||||||
|
BvhNode::Node {
|
||||||
|
parent_index: _,
|
||||||
|
child_l_index,
|
||||||
|
child_l_aabb,
|
||||||
|
child_r_index,
|
||||||
|
child_r_aabb,
|
||||||
|
} => {
|
||||||
|
assert!(child_l_aabb.min[axis as usize] <= child_l_aabb.max[axis as usize]);
|
||||||
|
assert!(child_r_aabb.min[axis as usize] <= child_r_aabb.max[axis as usize]);
|
||||||
|
if layer >= child_l_aabb.min[axis as usize]
|
||||||
|
&& layer <= child_l_aabb.max[axis as usize]
|
||||||
|
{
|
||||||
|
stack.push(child_l_index);
|
||||||
|
}
|
||||||
|
if layer >= child_r_aabb.min[axis as usize]
|
||||||
|
&& layer <= child_r_aabb.max[axis as usize]
|
||||||
|
{
|
||||||
|
stack.push(child_r_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BvhNode::Leaf {
|
||||||
|
parent_index: _,
|
||||||
|
shape_index,
|
||||||
|
} => {
|
||||||
|
for line in self.triangles[shape_index].intersect(layer, axis as usize) {
|
||||||
|
base_slice.lines.push(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
base_slice
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn outline_base_slice(&self, axis: Axis) -> BaseSlice {
|
||||||
|
let mut base_slice = BaseSlice {
|
||||||
|
i: 0,
|
||||||
|
d: 0.0,
|
||||||
|
axis,
|
||||||
|
lines: vec![],
|
||||||
|
};
|
||||||
|
'triangle: for (i, triangle) in self.triangles.iter().enumerate() {
|
||||||
|
let mut stack = Vec::<usize>::with_capacity(self.bvh.nodes.len());
|
||||||
|
stack.push(0);
|
||||||
|
let mut ab = false;
|
||||||
|
let mut ac = false;
|
||||||
|
let mut bc = false;
|
||||||
|
while let Some(i) = stack.pop() {
|
||||||
|
match self.bvh.nodes[i] {
|
||||||
|
BvhNode::Node {
|
||||||
|
parent_index: _,
|
||||||
|
child_l_index,
|
||||||
|
child_l_aabb,
|
||||||
|
child_r_index,
|
||||||
|
child_r_aabb,
|
||||||
|
} => {
|
||||||
|
let coords = [triangle.a, triangle.b, triangle.c];
|
||||||
|
macro_rules! match_aabb {
|
||||||
|
($side:expr) => {
|
||||||
|
coords
|
||||||
|
.iter()
|
||||||
|
.map(|point| {
|
||||||
|
$side.approx_contains_eps(point, FloatValue::EPSILON) as i32
|
||||||
|
})
|
||||||
|
.sum::<i32>()
|
||||||
|
>= 2
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if match_aabb!(child_l_aabb) {
|
||||||
|
stack.push(child_l_index);
|
||||||
|
}
|
||||||
|
if match_aabb!(child_r_aabb) {
|
||||||
|
stack.push(child_r_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BvhNode::Leaf {
|
||||||
|
parent_index: _,
|
||||||
|
shape_index,
|
||||||
|
} => {
|
||||||
|
if i == shape_index {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let other = &self.triangles[shape_index];
|
||||||
|
let a = triangle.has_point(other.a);
|
||||||
|
let b = triangle.has_point(other.b);
|
||||||
|
let c = triangle.has_point(other.c);
|
||||||
|
ab = ab || (a && b);
|
||||||
|
ac = ac || (a && c);
|
||||||
|
bc = bc || (b && c);
|
||||||
|
|
||||||
|
if ab && ac && bc {
|
||||||
|
continue 'triangle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base_slice
|
||||||
|
}
|
||||||
|
}
|
||||||
165
bampy/src/lib.rs
165
bampy/src/lib.rs
@@ -1,7 +1,11 @@
|
|||||||
|
#![feature(extract_if)]
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
use approx::relative_eq;
|
use approx::relative_eq;
|
||||||
use nalgebra::{point, vector, Vector3};
|
use nalgebra::{point, vector, Vector3};
|
||||||
|
use num::Float;
|
||||||
use result::{Slice, SliceOptions, SliceResult};
|
use result::{Slice, SliceOptions, SliceResult};
|
||||||
use slicer::axis::Axis;
|
use slicer::{axis::Axis, slice_path::SlicePath, trace_surface::trace_surface};
|
||||||
use wasm_bindgen::prelude::wasm_bindgen;
|
use wasm_bindgen::prelude::wasm_bindgen;
|
||||||
|
|
||||||
use crate::slicer::{mesh::Mesh, split_surface::split_surface, triangle::Triangle, FloatValue};
|
use crate::slicer::{mesh::Mesh, split_surface::split_surface, triangle::Triangle, FloatValue};
|
||||||
@@ -48,13 +52,10 @@ pub fn slice(
|
|||||||
);
|
);
|
||||||
|
|
||||||
slicable_triangles.push(triangle);
|
slicable_triangles.push(triangle);
|
||||||
let angle = triangle.normal.angle(&BED_NORMAL);
|
let mut normal = triangle.normal.clone();
|
||||||
let opposite_angle = std::f64::consts::PI - angle;
|
normal.z = normal.z.abs();
|
||||||
if angle <= max_angle
|
let angle = normal.angle(&BED_NORMAL);
|
||||||
|| relative_eq!(angle, max_angle)
|
if angle <= max_angle || relative_eq!(angle, max_angle) {
|
||||||
|| opposite_angle <= max_angle
|
|
||||||
|| relative_eq!(opposite_angle, max_angle)
|
|
||||||
{
|
|
||||||
surface_triangles.push(triangle);
|
surface_triangles.push(triangle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,45 +63,130 @@ pub fn slice(
|
|||||||
surface_triangles.shrink_to_fit();
|
surface_triangles.shrink_to_fit();
|
||||||
|
|
||||||
console_log!("Creating Surfaces");
|
console_log!("Creating Surfaces");
|
||||||
let surfaces = split_surface(surface_triangles).into_iter().map(|mesh| {
|
let min_surface_area = std::f64::consts::PI * (nozzle_diameter / 2.0).powi(2);
|
||||||
mesh.slice_surface(Axis::X, nozzle_diameter).filter(|path| {
|
let mut surfaces = split_surface(surface_triangles)
|
||||||
let mut length = 0.0;
|
.into_iter()
|
||||||
for pair in path.path.windows(2) {
|
.filter(|mesh| {
|
||||||
length += (pair[0].coords - pair[1].coords).norm();
|
let mut surface_area = 0.0;
|
||||||
if length >= min_surface_path_length {
|
for triangle in &mesh.triangles {
|
||||||
|
surface_area += triangle.area();
|
||||||
|
if surface_area >= min_surface_area {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
})
|
})
|
||||||
});
|
.map(|mesh| {
|
||||||
|
let outline = mesh
|
||||||
|
.outline_base_slice(Axis::Z)
|
||||||
|
.find_paths()
|
||||||
|
.into_iter()
|
||||||
|
.filter(|path| path.closed)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let surface = mesh
|
||||||
|
.slice_surface(Axis::X, nozzle_diameter)
|
||||||
|
.filter(|path| {
|
||||||
|
let mut length = 0.0;
|
||||||
|
for pair in path.path.windows(2) {
|
||||||
|
length += (pair[0].coords - pair[1].coords).norm();
|
||||||
|
if length >= min_surface_path_length {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
(mesh, outline, surface)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
surfaces
|
||||||
|
.sort_unstable_by(|(a, _, _), (b, _, _)| a.aabb.min.z.partial_cmp(&b.aabb.min.z).unwrap());
|
||||||
|
|
||||||
console_log!("Creating Walls");
|
console_log!("Creating Walls");
|
||||||
let wallMesh = Mesh::from(slicable_triangles);
|
let wallMesh = Mesh::from(slicable_triangles);
|
||||||
let walls = wallMesh.slice_paths(Axis::Z, layer_height);
|
let mut walls = wallMesh
|
||||||
|
.slice_paths(Axis::Z, layer_height)
|
||||||
|
.flat_map(|paths| paths.into_iter().filter(|path| path.closed))
|
||||||
|
.collect::<VecDeque<_>>();
|
||||||
|
let mut active_surfaces = Vec::new();
|
||||||
|
let mut out = Vec::new();
|
||||||
|
|
||||||
/*console_log!("Tracing Surfaces");
|
console_log!("Resolving dependencies");
|
||||||
let a = max_angle.tan();
|
while let Some(mut wall) = walls.pop_front() {
|
||||||
for slice in &mut slices {
|
active_surfaces.extend(
|
||||||
for surface in &surfaces {
|
surfaces
|
||||||
if surface.aabb.min.z <= slice.z && surface.aabb.max.z > slice.z {
|
.extract_if(|surface| surface.0.aabb.min.z <= wall.aabb.max.z)
|
||||||
trace_surface(slice, surface, a);
|
.map(|surface| (surface, Vec::new())),
|
||||||
|
);
|
||||||
|
|
||||||
|
let deactivate =
|
||||||
|
active_surfaces.extract_if(|element| element.0 .0.aabb.max.z < wall.aabb.min.z);
|
||||||
|
for (surface, surface_walls) in deactivate {
|
||||||
|
for ring in surface.1 {
|
||||||
|
out.push(ring.points);
|
||||||
|
}
|
||||||
|
for path in surface.2 {
|
||||||
|
out.push(path.path);
|
||||||
|
}
|
||||||
|
for wall in surface_walls {
|
||||||
|
walls.push_front(wall);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}*/
|
|
||||||
|
for surface in active_surfaces.iter_mut() {
|
||||||
|
let held = wall
|
||||||
|
.points
|
||||||
|
.extract_if(|point| !trace_surface(&point, &surface.0 .0, max_angle))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
if !held.is_empty() {
|
||||||
|
surface.1.push(SlicePath {
|
||||||
|
points: held,
|
||||||
|
..wall
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !wall.points.is_empty() {
|
||||||
|
out.push(wall.points);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
console_log!("Done");
|
console_log!("Done");
|
||||||
SliceResult {
|
SliceResult {
|
||||||
slices: surfaces
|
slices: out
|
||||||
.flatten()
|
.into_iter()
|
||||||
.map(|slice| Slice::Ring {
|
.map(|slice| Slice::Ring {
|
||||||
position: slice
|
position: slice
|
||||||
.path
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map(|point| [point.x as f32, point.y as f32, point.z as f32])
|
.flat_map(|point| [point.x as f32, point.y as f32, point.z as f32])
|
||||||
.collect(),
|
.collect(),
|
||||||
})
|
})
|
||||||
/*.chain(walls.flatten().map(|slice| {
|
.collect(),
|
||||||
|
}
|
||||||
|
/*SliceResult {
|
||||||
|
slices: surfaces
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|(_, outlines, slices)| {
|
||||||
|
outlines
|
||||||
|
.into_iter()
|
||||||
|
.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(slices.into_iter().map(|slice| {
|
||||||
|
Slice::Ring {
|
||||||
|
position: slice
|
||||||
|
.path
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|point| [point.x as f32, point.y as f32, point.z as f32])
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
.chain(walls.flatten().map(|slice| {
|
||||||
Slice::Ring {
|
Slice::Ring {
|
||||||
position: slice
|
position: slice
|
||||||
.points
|
.points
|
||||||
@@ -108,28 +194,7 @@ pub fn slice(
|
|||||||
.flat_map(|point| [point.x as f32, point.y as f32, point.z as f32])
|
.flat_map(|point| [point.x as f32, point.y as f32, point.z as f32])
|
||||||
.collect(),
|
.collect(),
|
||||||
}
|
}
|
||||||
}))*/
|
}))
|
||||||
/*.chain(surfaces.into_iter().map(|surface| {
|
|
||||||
Slice::Surface {
|
|
||||||
position: surface
|
|
||||||
.triangles
|
|
||||||
.into_iter()
|
|
||||||
.flat_map(|triangle| {
|
|
||||||
[
|
|
||||||
triangle.a.x as f32,
|
|
||||||
triangle.a.y as f32,
|
|
||||||
triangle.a.z as f32,
|
|
||||||
triangle.b.x as f32,
|
|
||||||
triangle.b.y as f32,
|
|
||||||
triangle.b.z as f32,
|
|
||||||
triangle.c.x as f32,
|
|
||||||
triangle.c.y as f32,
|
|
||||||
triangle.c.z as f32,
|
|
||||||
]
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
}
|
|
||||||
}))*/
|
|
||||||
.collect(),
|
.collect(),
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ use nalgebra::Vector3;
|
|||||||
|
|
||||||
use super::FloatValue;
|
use super::FloatValue;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||||
#[repr(usize)]
|
#[repr(usize)]
|
||||||
pub enum Axis {
|
pub enum Axis {
|
||||||
|
#[default]
|
||||||
X = 0,
|
X = 0,
|
||||||
Y = 1,
|
Y = 1,
|
||||||
Z = 2,
|
Z = 2,
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ pub struct Line3 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Line3 {
|
impl Line3 {
|
||||||
|
pub fn new(start: Point3<FloatValue>, end: Point3<FloatValue>) -> Self {
|
||||||
|
Self { start, end }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn norm(&self) -> FloatValue {
|
pub fn norm(&self) -> FloatValue {
|
||||||
(self.end - self.start).norm()
|
(self.end - self.start).norm()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use super::{
|
use super::{
|
||||||
axis::Axis,
|
axis::Axis,
|
||||||
base_slices::BaseSlice,
|
base_slices::BaseSlice,
|
||||||
|
line::Line3,
|
||||||
slice_path::{SlicePath, SurfacePathIterator},
|
slice_path::{SlicePath, SurfacePathIterator},
|
||||||
triangle::Triangle,
|
triangle::Triangle,
|
||||||
FloatValue,
|
FloatValue,
|
||||||
@@ -60,7 +61,7 @@ impl Mesh {
|
|||||||
/ slice_height)
|
/ slice_height)
|
||||||
.floor() as usize;
|
.floor() as usize;
|
||||||
|
|
||||||
(0..layer_count).map(move |i| {
|
(0..=layer_count).map(move |i| {
|
||||||
let layer = i as FloatValue * slice_height + self.aabb.min[axis as usize];
|
let layer = i as FloatValue * slice_height + self.aabb.min[axis as usize];
|
||||||
let mut base_slice = BaseSlice {
|
let mut base_slice = BaseSlice {
|
||||||
i,
|
i,
|
||||||
@@ -107,4 +108,79 @@ impl Mesh {
|
|||||||
base_slice
|
base_slice
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn outline_base_slice(&self, axis: Axis) -> BaseSlice {
|
||||||
|
let mut base_slice = BaseSlice {
|
||||||
|
i: 0,
|
||||||
|
d: 0.0,
|
||||||
|
axis,
|
||||||
|
lines: vec![],
|
||||||
|
};
|
||||||
|
'triangle: for (triangle_index, triangle) in self.triangles.iter().enumerate() {
|
||||||
|
let mut stack = Vec::<usize>::with_capacity(self.bvh.nodes.len());
|
||||||
|
stack.push(0);
|
||||||
|
let mut ab = false;
|
||||||
|
let mut ac = false;
|
||||||
|
let mut bc = false;
|
||||||
|
while let Some(i) = stack.pop() {
|
||||||
|
match self.bvh.nodes[i] {
|
||||||
|
BvhNode::Node {
|
||||||
|
parent_index: _,
|
||||||
|
child_l_index,
|
||||||
|
child_l_aabb,
|
||||||
|
child_r_index,
|
||||||
|
child_r_aabb,
|
||||||
|
} => {
|
||||||
|
let coords = [triangle.a, triangle.b, triangle.c];
|
||||||
|
macro_rules! match_aabb {
|
||||||
|
($side:expr) => {
|
||||||
|
coords
|
||||||
|
.iter()
|
||||||
|
.map(|point| {
|
||||||
|
$side.approx_contains_eps(point, FloatValue::EPSILON) as i32
|
||||||
|
})
|
||||||
|
.sum::<i32>()
|
||||||
|
>= 2
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if match_aabb!(child_l_aabb) {
|
||||||
|
stack.push(child_l_index);
|
||||||
|
}
|
||||||
|
if match_aabb!(child_r_aabb) {
|
||||||
|
stack.push(child_r_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BvhNode::Leaf {
|
||||||
|
parent_index: _,
|
||||||
|
shape_index,
|
||||||
|
} => {
|
||||||
|
if triangle_index == shape_index {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let other = &self.triangles[shape_index];
|
||||||
|
let a = other.has_point(triangle.a);
|
||||||
|
let b = other.has_point(triangle.b);
|
||||||
|
let c = other.has_point(triangle.c);
|
||||||
|
ab = ab || (a && b);
|
||||||
|
ac = ac || (a && c);
|
||||||
|
bc = bc || (b && c);
|
||||||
|
|
||||||
|
if ab && ac && bc {
|
||||||
|
continue 'triangle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !ab {
|
||||||
|
base_slice.lines.push(Line3::new(triangle.a, triangle.b));
|
||||||
|
}
|
||||||
|
if !ac {
|
||||||
|
base_slice.lines.push(Line3::new(triangle.a, triangle.c));
|
||||||
|
}
|
||||||
|
if !bc {
|
||||||
|
base_slice.lines.push(Line3::new(triangle.b, triangle.c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base_slice
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use nalgebra::{vector, Point, TAffine, Transform, Vector2, Vector3};
|
|||||||
use super::FloatValue;
|
use super::FloatValue;
|
||||||
|
|
||||||
pub trait Sdf<const D: usize> {
|
pub trait Sdf<const D: usize> {
|
||||||
fn sdf(&self, p: Point<FloatValue, D>) -> FloatValue;
|
fn sdf(&self, p: &Point<FloatValue, D>) -> FloatValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
@@ -19,7 +19,7 @@ impl SdfSphere {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Sdf<3> for SdfSphere {
|
impl Sdf<3> for SdfSphere {
|
||||||
fn sdf(&self, p: Point<FloatValue, 3>) -> FloatValue {
|
fn sdf(&self, p: &Point<FloatValue, 3>) -> FloatValue {
|
||||||
p.coords.norm() - self.radius
|
p.coords.norm() - self.radius
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -36,7 +36,7 @@ impl SdfBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Sdf<3> for SdfBox {
|
impl Sdf<3> for SdfBox {
|
||||||
fn sdf(&self, p: Point<FloatValue, 3>) -> FloatValue {
|
fn sdf(&self, p: &Point<FloatValue, 3>) -> FloatValue {
|
||||||
let q = p.coords.abs() - self.size.coords;
|
let q = p.coords.abs() - self.size.coords;
|
||||||
q.sup(&Vector3::zeros()).add_scalar(q.max().min(0.0)).norm()
|
q.sup(&Vector3::zeros()).add_scalar(q.max().min(0.0)).norm()
|
||||||
}
|
}
|
||||||
@@ -56,7 +56,7 @@ impl SdfInfiniteCone {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Sdf<3> for SdfInfiniteCone {
|
impl Sdf<3> for SdfInfiniteCone {
|
||||||
fn sdf(&self, p: Point<FloatValue, 3>) -> FloatValue {
|
fn sdf(&self, p: &Point<FloatValue, 3>) -> FloatValue {
|
||||||
let q = vector![p.coords.xy().norm(), p.z];
|
let q = vector![p.coords.xy().norm(), p.z];
|
||||||
let d = (q - self.angle.scale(q.dot(&self.angle).max(0.0))).norm();
|
let d = (q - self.angle.scale(q.dot(&self.angle).max(0.0))).norm();
|
||||||
if q.x * self.angle.y - q.y * self.angle.x > 0.0 {
|
if q.x * self.angle.y - q.y * self.angle.x > 0.0 {
|
||||||
@@ -80,8 +80,8 @@ impl<T: Sdf<3>> SdfTransform<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Sdf<3>> Sdf<3> for SdfTransform<T> {
|
impl<T: Sdf<3>> Sdf<3> for SdfTransform<T> {
|
||||||
fn sdf(&self, p: Point<FloatValue, 3>) -> FloatValue {
|
fn sdf(&self, p: &Point<FloatValue, 3>) -> FloatValue {
|
||||||
self.sdf.sdf(self.transform.inverse_transform_point(&p))
|
self.sdf.sdf(&self.transform.inverse_transform_point(p))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,8 +98,8 @@ impl<const D: usize, T: Sdf<D>> SdfScale<D, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<const D: usize, T: Sdf<D>> Sdf<D> for SdfScale<D, T> {
|
impl<const D: usize, T: Sdf<D>> Sdf<D> for SdfScale<D, T> {
|
||||||
fn sdf(&self, p: Point<FloatValue, D>) -> FloatValue {
|
fn sdf(&self, p: &Point<FloatValue, D>) -> FloatValue {
|
||||||
self.sdf.sdf(p / self.scale) * self.scale
|
self.sdf.sdf(&(p / self.scale)) * self.scale
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ impl<T: Sdf<3>> SdfOnion<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Sdf<3>> Sdf<3> for SdfOnion<T> {
|
impl<T: Sdf<3>> Sdf<3> for SdfOnion<T> {
|
||||||
fn sdf(&self, p: Point<FloatValue, 3>) -> FloatValue {
|
fn sdf(&self, p: &Point<FloatValue, 3>) -> FloatValue {
|
||||||
self.sdf.sdf(p).abs() - self.thickness
|
self.sdf.sdf(p).abs() - self.thickness
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,7 +134,7 @@ impl<const D: usize, T: Sdf<D>, U: Sdf<D>> SdfUnion<D, T, U> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<const D: usize, T: Sdf<D>, U: Sdf<D>> Sdf<D> for SdfUnion<D, T, U> {
|
impl<const D: usize, T: Sdf<D>, U: Sdf<D>> Sdf<D> for SdfUnion<D, T, U> {
|
||||||
fn sdf(&self, p: Point<FloatValue, D>) -> FloatValue {
|
fn sdf(&self, p: &Point<FloatValue, D>) -> FloatValue {
|
||||||
self.sdf_a.sdf(p).min(self.sdf_b.sdf(p))
|
self.sdf_a.sdf(p).min(self.sdf_b.sdf(p))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -152,7 +152,7 @@ impl<const D: usize, T: Sdf<D>, U: Sdf<D>> SdfIntersection<D, T, U> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<const D: usize, T: Sdf<D>, U: Sdf<D>> Sdf<D> for SdfIntersection<D, T, U> {
|
impl<const D: usize, T: Sdf<D>, U: Sdf<D>> Sdf<D> for SdfIntersection<D, T, U> {
|
||||||
fn sdf(&self, p: Point<FloatValue, D>) -> FloatValue {
|
fn sdf(&self, p: &Point<FloatValue, D>) -> FloatValue {
|
||||||
self.sdf_a.sdf(p).max(self.sdf_b.sdf(p))
|
self.sdf_a.sdf(p).max(self.sdf_b.sdf(p))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,7 +170,7 @@ impl<const D: usize, T: Sdf<D>, U: Sdf<D>> SdfDifference<D, T, U> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<const D: usize, T: Sdf<D>, U: Sdf<D>> Sdf<D> for SdfDifference<D, T, U> {
|
impl<const D: usize, T: Sdf<D>, U: Sdf<D>> Sdf<D> for SdfDifference<D, T, U> {
|
||||||
fn sdf(&self, p: Point<FloatValue, D>) -> FloatValue {
|
fn sdf(&self, p: &Point<FloatValue, D>) -> FloatValue {
|
||||||
self.sdf_a.sdf(p).max(-self.sdf_b.sdf(p))
|
self.sdf_a.sdf(p).max(-self.sdf_b.sdf(p))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use std::ops::RangeInclusive;
|
use std::{collections::VecDeque, ops::RangeInclusive};
|
||||||
|
|
||||||
use approx::relative_eq;
|
use approx::relative_eq;
|
||||||
use bvh::aabb::Aabb;
|
use bvh::aabb::Aabb;
|
||||||
@@ -6,7 +6,7 @@ use nalgebra::Point3;
|
|||||||
|
|
||||||
use super::{axis::Axis, mesh::Mesh, FloatValue};
|
use super::{axis::Axis, mesh::Mesh, FloatValue};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Default)]
|
||||||
pub struct SlicePath {
|
pub struct SlicePath {
|
||||||
pub i: usize,
|
pub i: usize,
|
||||||
pub d: FloatValue,
|
pub d: FloatValue,
|
||||||
@@ -75,6 +75,34 @@ impl SurfacePathIterator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn squish(points: &mut Vec<Point3<FloatValue>>, axis: Axis, d: FloatValue) {
|
||||||
|
macro_rules! ax {
|
||||||
|
($p: expr) => {
|
||||||
|
$p.coords[axis as usize]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
let first = ax!(points.first().unwrap());
|
||||||
|
let left = points.iter().position(|p| first - ax!(p) > d);
|
||||||
|
let last = ax!(points.last().unwrap());
|
||||||
|
let right = points.iter().rposition(|p| ax!(p) - last > d);
|
||||||
|
|
||||||
|
if let (Some(left), Some(right)) = (left, right) {
|
||||||
|
if left > right {
|
||||||
|
// TODO
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let total = ax!(points[left + 1]) - first;
|
||||||
|
let delta = ax!(points[left]) - ax!(points[left + 1]);
|
||||||
|
points.splice(
|
||||||
|
0..left,
|
||||||
|
vec![points[left].lerp(&points[left + 1], (d - total) / delta)],
|
||||||
|
);
|
||||||
|
|
||||||
|
let total = last - ax!(points[right + 1]);
|
||||||
|
let delta = ax!(points[right + 1]) - ax!(points[right]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Iterator for SurfacePathIterator {
|
impl Iterator for SurfacePathIterator {
|
||||||
type Item = SurfacePath;
|
type Item = SurfacePath;
|
||||||
|
|
||||||
@@ -82,8 +110,10 @@ impl Iterator for SurfacePathIterator {
|
|||||||
self.slices.retain_mut(|slice| !slice.is_empty());
|
self.slices.retain_mut(|slice| !slice.is_empty());
|
||||||
|
|
||||||
let (h_axis, _) = self.axis.other();
|
let (h_axis, _) = self.axis.other();
|
||||||
|
let mut iter = self.slices.iter_mut();
|
||||||
|
|
||||||
let ring = self.slices.first_mut()?.pop()?;
|
let mut ring = iter.next()?.pop()?;
|
||||||
|
// TODO: squish(&mut ring.points, h_axis, self.nozzle_width);
|
||||||
let mut item = Self::Item {
|
let mut item = Self::Item {
|
||||||
i: ring.i..=ring.i,
|
i: ring.i..=ring.i,
|
||||||
d: ring.d..=ring.d,
|
d: ring.d..=ring.d,
|
||||||
@@ -92,7 +122,7 @@ impl Iterator for SurfacePathIterator {
|
|||||||
path: ring.points,
|
path: ring.points,
|
||||||
};
|
};
|
||||||
|
|
||||||
for slice in self.slices.iter_mut().skip(1) {
|
for slice in iter {
|
||||||
if *item.i.end() != slice[0].i - 1 {
|
if *item.i.end() != slice[0].i - 1 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -136,9 +166,11 @@ impl Iterator for SurfacePathIterator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(mut ring) = index.map(|i| slice.remove(i)) {
|
if let Some(mut ring) = index.map(|i| slice.remove(i)) {
|
||||||
|
// TODO: squish(&mut ring.points, h_axis, self.nozzle_width);
|
||||||
if needs_reverse {
|
if needs_reverse {
|
||||||
ring.points.reverse();
|
ring.points.reverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
item.i = *item.i.start()..=ring.i;
|
item.i = *item.i.start()..=ring.i;
|
||||||
item.d = *item.d.start()..=ring.d;
|
item.d = *item.d.start()..=ring.d;
|
||||||
item.path.append(&mut ring.points);
|
item.path.append(&mut ring.points);
|
||||||
|
|||||||
@@ -1,47 +1,48 @@
|
|||||||
use bvh::bvh::BvhNode;
|
use bvh::bvh::BvhNode;
|
||||||
|
use nalgebra::Point3;
|
||||||
|
|
||||||
use super::{mesh::Mesh, slice_path::SlicePath, z_projection::ToolpathIntersects, FloatValue};
|
use crate::slicer::sdf::Sdf3dModifiers;
|
||||||
|
|
||||||
pub fn trace_surface(slice: &mut SlicePath, surface: &Mesh, a: FloatValue) {
|
use super::{
|
||||||
slice.points.retain_mut(|point| {
|
mesh::Mesh,
|
||||||
let mut stack = Vec::<usize>::new();
|
sdf::{Sdf, SdfInfiniteCone},
|
||||||
stack.push(0);
|
z_projection::ToolpathIntersects,
|
||||||
while let Some(i) = stack.pop() {
|
FloatValue,
|
||||||
match surface.bvh.nodes[i] {
|
};
|
||||||
BvhNode::Node {
|
|
||||||
parent_index: _,
|
pub fn trace_surface(point: &Point3<FloatValue>, surface: &Mesh, a: FloatValue) -> bool {
|
||||||
child_l_index,
|
let sdf = SdfInfiniteCone::new(a);
|
||||||
child_l_aabb,
|
let mut stack = Vec::<usize>::new();
|
||||||
child_r_index,
|
stack.push(0);
|
||||||
child_r_aabb,
|
while let Some(i) = stack.pop() {
|
||||||
} => {
|
match surface.bvh.nodes[i] {
|
||||||
if child_l_aabb.toolpath_intersects(point, a) {
|
BvhNode::Node {
|
||||||
stack.push(child_l_index);
|
parent_index: _,
|
||||||
}
|
child_l_index,
|
||||||
if child_r_aabb.toolpath_intersects(point, a) {
|
child_l_aabb,
|
||||||
stack.push(child_r_index);
|
child_r_index,
|
||||||
}
|
child_r_aabb,
|
||||||
|
} => {
|
||||||
|
if child_l_aabb.toolpath_intersects(point, a) {
|
||||||
|
stack.push(child_l_index);
|
||||||
}
|
}
|
||||||
BvhNode::Leaf {
|
if child_r_aabb.toolpath_intersects(point, a) {
|
||||||
parent_index: _,
|
stack.push(child_r_index);
|
||||||
shape_index,
|
}
|
||||||
} => {
|
}
|
||||||
let triangle = &surface.triangles[shape_index];
|
BvhNode::Leaf {
|
||||||
macro_rules! check {
|
parent_index: _,
|
||||||
( $var:ident ) => {{
|
shape_index,
|
||||||
let x = point.x - triangle.$var.x;
|
} => {
|
||||||
let y = point.y - triangle.$var.y;
|
let triangle = &surface.triangles[shape_index];
|
||||||
(point.z > triangle.aabb.min.z
|
if sdf.translate(triangle.a).sdf(point) < 0.0
|
||||||
&& FloatValue::sqrt(x * x + y * y)
|
|| sdf.translate(triangle.b).sdf(point) < 0.0
|
||||||
< (triangle.$var.z - point.z).abs() * a)
|
|| sdf.translate(triangle.c).sdf(point) < 0.0
|
||||||
}};
|
{
|
||||||
}
|
return false;
|
||||||
if check!(a) || check!(b) || check!(c) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
true
|
}
|
||||||
});
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ impl Triangle {
|
|||||||
a,
|
a,
|
||||||
b,
|
b,
|
||||||
c,
|
c,
|
||||||
normal: (b - a).cross(&(c - a)).into(),
|
normal: (b - a).cross(&(c - a)).normalize(),
|
||||||
node_index: 0,
|
node_index: 0,
|
||||||
aabb,
|
aabb,
|
||||||
}
|
}
|
||||||
@@ -44,13 +44,6 @@ impl Triangle {
|
|||||||
self.has_point(other.a) || self.has_point(other.b) || self.has_point(other.c)
|
self.has_point(other.a) || self.has_point(other.b) || self.has_point(other.c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shares_edge_with_triangle(&self, other: Triangle) -> bool {
|
|
||||||
let a = self.has_point(other.a);
|
|
||||||
let b = self.has_point(other.b);
|
|
||||||
let c = self.has_point(other.c);
|
|
||||||
a && b || a && c || b && c
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn intersect(&self, value: FloatValue, axis: usize) -> Option<Line3> {
|
pub fn intersect(&self, value: FloatValue, axis: usize) -> Option<Line3> {
|
||||||
let mut intersection = Vec::<Point3<FloatValue>>::with_capacity(3);
|
let mut intersection = Vec::<Point3<FloatValue>>::with_capacity(3);
|
||||||
let mut last = &self.c;
|
let mut last = &self.c;
|
||||||
|
|||||||
122
flake.nix
122
flake.nix
@@ -4,59 +4,77 @@
|
|||||||
rust-overlay.url = "github:oxalica/rust-overlay";
|
rust-overlay.url = "github:oxalica/rust-overlay";
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
};
|
};
|
||||||
outputs = {
|
outputs =
|
||||||
self,
|
{
|
||||||
nixpkgs,
|
self,
|
||||||
flake-utils,
|
nixpkgs,
|
||||||
rust-overlay,
|
flake-utils,
|
||||||
}:
|
rust-overlay,
|
||||||
flake-utils.lib.eachDefaultSystem (system: let
|
}:
|
||||||
overlays = [(import rust-overlay)];
|
flake-utils.lib.eachDefaultSystem (
|
||||||
pkgs = import nixpkgs {inherit system overlays;};
|
system:
|
||||||
rust-bin = pkgs.rust-bin.stable.latest.default.override {
|
let
|
||||||
targets = [ "wasm32-unknown-unknown" ];
|
overlays = [ (import rust-overlay) ];
|
||||||
extensions = ["rust-src" "rust-std" "clippy" "rust-analyzer"];
|
pkgs = import nixpkgs { inherit system overlays; };
|
||||||
};
|
rust-bin = pkgs.rust-bin.nightly.latest.default.override {
|
||||||
fontMin = pkgs.python311.withPackages (ps: with ps; [brotli fonttools] ++ (with fonttools.optional-dependencies; [woff]));
|
targets = [ "wasm32-unknown-unknown" ];
|
||||||
tauriPkgs = nixpkgs.legacyPackages.${system};
|
extensions = [
|
||||||
libraries = with tauriPkgs; [
|
"rust-src"
|
||||||
webkitgtk
|
"rust-std"
|
||||||
gtk3
|
"clippy"
|
||||||
cairo
|
"rust-analyzer"
|
||||||
gdk-pixbuf
|
];
|
||||||
glib
|
};
|
||||||
dbus
|
fontMin = pkgs.python311.withPackages (
|
||||||
openssl_3
|
ps:
|
||||||
librsvg
|
with ps;
|
||||||
];
|
[
|
||||||
packages =
|
brotli
|
||||||
(with pkgs; [
|
fonttools
|
||||||
nodejs_18
|
]
|
||||||
nodePackages.pnpm
|
++ (with fonttools.optional-dependencies; [ woff ])
|
||||||
rust-bin
|
);
|
||||||
fontMin
|
tauriPkgs = nixpkgs.legacyPackages.${system};
|
||||||
wasm-pack
|
libraries = with tauriPkgs; [
|
||||||
])
|
webkitgtk
|
||||||
++ (with tauriPkgs; [
|
gtk3
|
||||||
curl
|
cairo
|
||||||
wget
|
gdk-pixbuf
|
||||||
pkg-config
|
glib
|
||||||
dbus
|
dbus
|
||||||
openssl_3
|
openssl_3
|
||||||
glib
|
|
||||||
gtk3
|
|
||||||
libsoup
|
|
||||||
webkitgtk
|
|
||||||
librsvg
|
librsvg
|
||||||
# serial plugin
|
];
|
||||||
udev
|
packages =
|
||||||
]);
|
(with pkgs; [
|
||||||
in {
|
nodejs_18
|
||||||
devShell = pkgs.mkShell {
|
nodePackages.pnpm
|
||||||
buildInputs = packages;
|
rust-bin
|
||||||
shellHook = ''
|
fontMin
|
||||||
export LD_LIBRARY_PATH=${pkgs.lib.makeLibraryPath libraries}:$LD_LIBRARY_PATH
|
wasm-pack
|
||||||
'';
|
])
|
||||||
};
|
++ (with tauriPkgs; [
|
||||||
});
|
curl
|
||||||
|
wget
|
||||||
|
pkg-config
|
||||||
|
dbus
|
||||||
|
openssl_3
|
||||||
|
glib
|
||||||
|
gtk3
|
||||||
|
libsoup
|
||||||
|
webkitgtk
|
||||||
|
librsvg
|
||||||
|
# serial plugin
|
||||||
|
udev
|
||||||
|
]);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
devShell = pkgs.mkShell {
|
||||||
|
buildInputs = packages;
|
||||||
|
shellHook = ''
|
||||||
|
export LD_LIBRARY_PATH=${pkgs.lib.makeLibraryPath libraries}:$LD_LIBRARY_PATH
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,16 +33,17 @@
|
|||||||
progressLayer.set(event.data.layer);
|
progressLayer.set(event.data.layer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'layer': {
|
case 'result': {
|
||||||
layers.update((layers) => {
|
layers.update((layers) => {
|
||||||
const layer = event.data.data;
|
for (const layer of event.data.data.slices) {
|
||||||
if (layer.type === 'ring' || layer.type === 'path') {
|
if (layer.type === 'ring' || layer.type === 'path') {
|
||||||
layers.push(
|
layers.push(
|
||||||
Array.from({ length: layer.position.length / 3 }, (_, i) =>
|
Array.from({ length: layer.position.length / 3 }, (_, i) =>
|
||||||
new Vector3().fromArray(layer.position, i * 3)
|
new Vector3().fromArray(layer.position, i * 3)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
} else if (layer.type === 'surface') {
|
} else if (layer.type === 'surface') {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return layers;
|
return layers;
|
||||||
});
|
});
|
||||||
@@ -81,7 +82,7 @@
|
|||||||
tolerance,
|
tolerance,
|
||||||
maxNonPlanarAngle,
|
maxNonPlanarAngle,
|
||||||
nozzleDiameter,
|
nozzleDiameter,
|
||||||
minSurfacePathLength: nozzleDiameter * 4,
|
minSurfacePathLength: nozzleDiameter * 2,
|
||||||
bedNormal: bedNormal.toArray()
|
bedNormal: bedNormal.toArray()
|
||||||
}
|
}
|
||||||
} satisfies SliceEvent);
|
} satisfies SliceEvent);
|
||||||
@@ -111,7 +112,7 @@
|
|||||||
<!---{@const color = new Color(0, i / $layers.length, 0.2)}-->
|
<!---{@const color = new Color(0, i / $layers.length, 0.2)}-->
|
||||||
<T.Mesh {visible}>
|
<T.Mesh {visible}>
|
||||||
<MeshLineGeometry {points} />
|
<MeshLineGeometry {points} />
|
||||||
<MeshLineMaterial width={layerHeight / 6} {color} />
|
<MeshLineMaterial width={nozzleDiameter * 0.25} {color} />
|
||||||
</T.Mesh>
|
</T.Mesh>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
||||||
|
|||||||
@@ -22,11 +22,9 @@ addEventListener('message', async (event: MessageEvent<WorkerEvent>) => {
|
|||||||
nozzleDiameter: event.data.data.nozzleDiameter,
|
nozzleDiameter: event.data.data.nozzleDiameter,
|
||||||
minSurfacePathLength: event.data.data.minSurfacePathLength
|
minSurfacePathLength: event.data.data.minSurfacePathLength
|
||||||
});
|
});
|
||||||
for (const layer of result.slices) {
|
self.postMessage({
|
||||||
self.postMessage({
|
type: 'result',
|
||||||
type: 'layer',
|
data: result
|
||||||
data: layer
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user