diff --git a/src/gcode/mod.rs b/src/gcode/mod.rs index 5ba8921..73a0e32 100644 --- a/src/gcode/mod.rs +++ b/src/gcode/mod.rs @@ -54,7 +54,7 @@ impl GcodeWriter { self.write_gcode(format!(";\n; Layer {}\n;", n).as_str()); self.write_gcode( format!( - "G1 Z{} {}{} ; layer change", + "G0 Z{} {}{} ; layer change", z, feed_axis, feed_rate ).as_str() ); @@ -71,4 +71,4 @@ impl GcodeWriter { ).as_str() ); } -} \ No newline at end of file +} diff --git a/src/geometry/mod.rs b/src/geometry/mod.rs index d18c13b..9e00a87 100644 --- a/src/geometry/mod.rs +++ b/src/geometry/mod.rs @@ -41,6 +41,17 @@ pub struct BoundingBox { pub z_max: f32 } +/// +#[derive(Debug)] +pub struct OuterBox { + pub x_min: f32, + pub y_min: f32, + pub z_min: f32, + pub x_max: f32, + pub y_max: f32, + pub z_max: f32 +} + /// #[derive(Clone, Debug)] pub struct STLMesh { @@ -95,6 +106,35 @@ impl STLMesh { } } + pub fn outer_bounds(&self) -> OuterBox { + let mut minimums = Vec::with_capacity(3); + let mut maximums = Vec::with_capacity(3); + for i in 0..3 { + let mut min_vals = self.vertices[0][i]; + let mut max_vals = self.vertices[0][i]; + for row in self.vertices.iter().skip(1) { + if row[i] < min_vals { + min_vals = row[i]; + + } + if row[i] > max_vals { + max_vals = row[i]; + } + } + minimums.push(min_vals); + maximums.push(max_vals); + } + OuterBox { + x_min: minimums[0], + y_min: minimums[1], + z_min: minimums[2], + x_max: maximums[0], + y_max: maximums[1], + z_max: maximums[2] + } + + } + pub fn faces(&self) -> &Vec { &self.faces } diff --git a/src/main.rs b/src/main.rs index 92f84f3..6bbeec1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -69,9 +69,28 @@ fn main() { .map(|x| STLMesh::new(x.clone())) .collect(); - let z_offset = -1.0 * stl_meshes[0].bounding_box().z_min; - let _ = stl_meshes[0].translate(20.0,20.0,z_offset); + + // Testing some files, They are allegedly ok. So where is the problem? + let mut file_testing = std::fs::OpenOptions::new().read(true).open("test/example/Sphere.stl").unwrap(); + let mut stl = stl_io::read_stl(&mut file_testing).unwrap(); + + let Validation = stl_io::IndexedMesh::validate(&stl); + // println!("VALIDATION: {:?}",Validation); + // println!("X Min: {:?}",stl_meshes[0].bounding_box().x_min); + // println!("X Max: {:?}",stl_meshes[0].bounding_box().x_max); + // println!("Y Min: {:?}",stl_meshes[0].bounding_box().y_min); + // println!("Y Max: {:?}",stl_meshes[0].bounding_box().y_max); + // println!("Z Min: {:?}",stl_meshes[0].bounding_box().z_min); + // println!("Z Max: {:?}",stl_meshes[0].bounding_box().z_max); + // println!("Bounding Box: {:?}",stl_meshes[0].bounding_box()); + // println!("Faces: {:?}",stl_meshes[0].faces()[0].normal); + // println!("Vertices: {:?}",stl_meshes[0].vertices()); + // println!("My minimums: {:?}",stl_meshes[0].outer_bounds()); + let z_offset = -1.0 * stl_meshes[0].outer_bounds().z_min; + // println!("Z Offset: {:?}",z_offset); + let _ = stl_meshes[0].translate(30.0,30.0,z_offset); let _ = stl_meshes[0].scale(10.0, 10.0, 10.0); + let slicer = FFFSlicer::new(settings, stl_meshes); let _ = slicer.slice(&gcode_file); diff --git a/src/slicer/fff_slicer.rs b/src/slicer/fff_slicer.rs index 3460d3f..795c599 100644 --- a/src/slicer/fff_slicer.rs +++ b/src/slicer/fff_slicer.rs @@ -19,11 +19,24 @@ impl FFFSlicer { } } + pub fn wall_lines(&self, stl:&STLMesh, verts: Vec<[f32;2]>, ind: Vec, num_lines: u32) { + //testing wall ines + let num_wall_lines = num_lines-1; + + // for face in 0..ind.len() { + // println!("Face: {:?}",stl.faces()[ind[face]].normal); + // } + + + + } + pub fn perimeters(&self, stl: &STLMesh, gcode_writer: &mut GcodeWriter, z: f32) -> () { let tol = 1e-6 as f32; let tris = stl.triangles(); let perimeter_edges = Edges::new(); - + // println!("Normals, {:?}",stl.faces()[0].normal); + // println!("STL: {:?}",stl); // counter to track the index of the triangles that intersect with each z layer let mut counter = 0; @@ -34,10 +47,11 @@ impl FFFSlicer { // vector containing the intersection coordinates between the // triangles and the plane z_height let mut ab_coords = vec![]; - + let mut index = 0; + let mut used_indices = vec![]; // iterate through all the triangles in the stl for tri in tris.iter() { - + // break down vertices for easier handling (for me) let vert_1 = tri[0]; let vert_2 = tri[1]; @@ -45,13 +59,13 @@ impl FFFSlicer { - // if any of the vertices are above AND any are below, + // if any of the vertices of a triangle are above AND any are below z, if vert_1[2] < z || vert_2[2] < z || vert_3[2] < z { if vert_1[2] > z || vert_2[2] > z || vert_3[2] > z { // append the index of intersecting triangles vec.push(counter); - + used_indices.push(index); // Must sort the vertices to be able to calculate // the line segment created by the interception of // the z_height and the triangles that bound it. @@ -79,7 +93,8 @@ impl FFFSlicer { // There are three triangles possible: two vertices // below z_height and one above, two vertices above // z_height and one below, and one vertex coincident - // with z_height and one above and one below. In + // with z_height and one above and one below (Case not + // included, two coincident, one above or below). In // the first two cases, the single vertex will go into // the first index (0). In the last case, either // vertex not coincident with z_height will go into @@ -153,10 +168,11 @@ impl FFFSlicer { let b_coord = [xb, yb]; ab_coords.push([a_coord, b_coord]); } + // println!("Test Used Indices: {:?}",used_indices) } // increase counter for next triangle counter += 1; - + index += 1; } // end looping through all triangles for a layer at z_height println!("Global Layer height; {:?}", z); @@ -164,21 +180,33 @@ impl FFFSlicer { // println!("Sample AB-Coords: {:?}",ab_coords[0]); // println!("Going Crazy: {:?}", ab_coords); // Testing to sort the perimeter lines (ab) - let TEST = 1; + // let TEST = 1; // if TEST == 1 { //16.5 { // println!("All AB-Coords: {:?}", ab_coords); // perimeter array of the sorted line segments let mut perimeter_sort = Vec::new(); + let mut used_indices_sort = vec![]; + let mut perimeter_verts = vec![]; + // Clone the vector of all line segments, we // will be removing all used segments let mut AB_COORDS = Vec::from(ab_coords.clone()); - // push the first line segment to the sorted - // list, the exact place to start will need - // to be adjusted in the future. + + // As long as the coordinate list is not empty, + // continue to sort them in order of closest. + // TODO adding capabilities to deal with islands + // in the mesh if AB_COORDS.len() > 0 { - perimeter_sort.push(AB_COORDS[0]); + // push the first line segment to the sorted + // list, the exact place to start will need + // to be adjusted in the future. + perimeter_sort.push(AB_COORDS[0]); + // perimeter_verts.push(perimeter_sort[0][0]); + perimeter_verts.push(perimeter_sort[0][1]); + used_indices_sort.push(used_indices[0]); + used_indices.swap_remove(0); // remove the first line segment AB_COORDS.swap_remove(0); // create a counter variable @@ -192,11 +220,15 @@ impl FFFSlicer { // Search radius for next line segment. let mut search_radius = 1.0e-3; - + // dummy variable. Need this to check if next point is an island + let mut last_radius = 1.0e-3; // while the number of available line segments is // above some number, keep building the connected // lines + let mut cycle_count = 0; + while num_available_segs > 0 { + // index counter, for the triangle in AB_COORDS let mut index_count = 0; // vector to save the matcing indices. This @@ -279,7 +311,7 @@ impl FFFSlicer { if euclidean <= search_radius { // if y_diff <= search_radius { // println!("--------------------------------------"); - // println!("Match Found"); + // println!("Test"); // println!("euclindean A: {:?}",euclidean_b); // println!("euclindean B: {:?}",euclidean_b); // println!("euclindean B: {:?}",euclidean_b); @@ -289,8 +321,9 @@ impl FFFSlicer { // println!("Searched X: {:?}, Searched Y: {:?}", perimeter_sort.last().expect("Perimeter is empty")[1][0], perimeter_sort.last().expect("Perimeter is empty")[1][1]); // println!("X diff: {:?}",x_diff); // println!("Y diff: {:?}",y_diff); - // println!("Euclidean: {:?}",euclidean); - // println!("Search Radius: {:?}", search_radius); + println!("Euclidean: {:?}",euclidean); + println!("Search Radius: {:?}", search_radius); + println!("Coords: {:?}",AB_COORDS[index_count]); // perimeter_sort.push(*segs); index_match.push(index_count); vertex_switch.push(which_vertex); @@ -306,11 +339,16 @@ impl FFFSlicer { // the search. If none are found, grow the search radus, and // repeat the search. (Hopefully). // - // println!("NUM INDEXES: {:?}",index_match.len()); - // println!("INDEXES: {:?}",index_match); - // println!("----------------------------------"); + println!("NUM INDEXES: {:?}",index_match.len()); + println!("INDEXES: {:?}",index_match); + println!("Cycle Count: {:?}",cycle_count); + println!("----------------------------------"); if index_match.len() == 1 { + println!("Num Available Segs: {:?}", num_available_segs); + // println!("Used Indices: {:?}", used_indices); perimeter_sort.push(AB_COORDS[index_match[0]]); + used_indices_sort.push(used_indices[index_match[0]]); + // println!("Sorted Used Indices: {:?}",used_indices_sort); // println!("Size of index match: {:?}",index_match.len()); // AB_COORDS.swap_remove(index_count); // println!("Test index match: {:?}", index_match); @@ -319,18 +357,97 @@ impl FFFSlicer { num_available_segs -= 1; let REMOVE = *index_match.last().expect("Nothing in the perimeter"); AB_COORDS.swap_remove(REMOVE); + used_indices.swap_remove(REMOVE); // println!("Size of AB_COUNT: {:?}",AB_COORDS.len()); search_radius = 1e-3; gcode_writer.write_perimeter(perimeter_sort.last().unwrap()[1][0],perimeter_sort.last().unwrap()[1][1],z,555.0,1200.0); + perimeter_verts.push([perimeter_sort.last().unwrap()[1][0],perimeter_sort.last().unwrap()[1][1]]); + // if the number of matching indices is 2 and we have iterated over 20000 + // this might be the case when finding a new island, and the closest two + // segments are the same distance away from the last point. + } else if index_match.len() == 2 && cycle_count > 10000{ + println!("*********************DID THIS WORK??????******************"); + println!("Search Radius: {:?}", search_radius); + println!("Cycle Count: {:?}",cycle_count); + println!("NUM INDEXES: {:?}",index_match.len()); + if index_match.len() == 2 { + println!("Num Available Segs: {:?}", num_available_segs); + // println!("Used Indices: {:?}", used_indices); + perimeter_sort.push(AB_COORDS[index_match[0]]); + used_indices_sort.push(used_indices[index_match[0]]); + // println!("Sorted Used Indices: {:?}",used_indices_sort); + // println!("Size of index match: {:?}",index_match.len()); + // AB_COORDS.swap_remove(index_count); + // println!("Test index match: {:?}", index_match); + // println!("Size of AB_COUNT: {:?}",AB_COORDS.len()); + // println!("Sorted Segments: {:?}",perimeter_sort); + num_available_segs -= 1; + let REMOVE = *index_match.last().expect("Nothing in the perimeter"); + AB_COORDS.swap_remove(REMOVE); + used_indices.swap_remove(REMOVE); + // println!("Size of AB_COUNT: {:?}",AB_COORDS.len()); + search_radius = 1e-3; + gcode_writer.write_perimeter(perimeter_sort.last().unwrap()[1][0],perimeter_sort.last().unwrap()[1][1],z,555.0,1200.0); + perimeter_verts.push([perimeter_sort.last().unwrap()[1][0],perimeter_sort.last().unwrap()[1][1]]); + } + // if the number of matching indices is greater than 1, + // shrink the search radius } else if index_match.len() > 1 { - search_radius = search_radius * 0.9; + search_radius = search_radius * 0.99; + if search_radius < (1e-3)/1000.0 { + break + } + // if the number of matching pairs is zero, + // grow the search radius } else { - search_radius = search_radius * 1.1; + search_radius = search_radius * 1.015; + // if search_radius > 1000.0*(1e-3) { + // break + // } } + cycle_count += 1; + if cycle_count > 40000 { + println!("Search Radius: {:?}", search_radius); + println!("Cycle Count: {:?}",cycle_count); + println!("NUM INDEXES: {:?}",index_match.len()); + if index_match.len() == 2 { + println!("Num Available Segs: {:?}", num_available_segs); + // println!("Used Indices: {:?}", used_indices); + perimeter_sort.push(AB_COORDS[index_match[0]]); + used_indices_sort.push(used_indices[index_match[0]]); + // println!("Sorted Used Indices: {:?}",used_indices_sort); + // println!("Size of index match: {:?}",index_match.len()); + // AB_COORDS.swap_remove(index_count); + // println!("Test index match: {:?}", index_match); + // println!("Size of AB_COUNT: {:?}",AB_COORDS.len()); + // println!("Sorted Segments: {:?}",perimeter_sort); + num_available_segs -= 1; + let REMOVE = *index_match.last().expect("Nothing in the perimeter"); + AB_COORDS.swap_remove(REMOVE); + used_indices.swap_remove(REMOVE); + // println!("Size of AB_COUNT: {:?}",AB_COORDS.len()); + search_radius = 1e-3; + gcode_writer.write_perimeter(perimeter_sort.last().unwrap()[1][0],perimeter_sort.last().unwrap()[1][1],z,555.0,1200.0); + perimeter_verts.push([perimeter_sort.last().unwrap()[1][0],perimeter_sort.last().unwrap()[1][1]]); + + } + else { + break; + } + // break; + } } // println!("Sorted Segments: {:?}",perimeter_sort); + // println!("Used Indices: {:?}",used_indices_sort); + // println!("Perimeter Chords Sort: {:?}",perimeter_sort); + // println!("Perimeter Vert Sort: {:?}",perimeter_verts); + // println!("Face: {:?}",stl.faces()[used_indices_sort[0]].normal); + // let mut faces = vec![]; + // println!("TEst: {:?}", used_indices_sort.len()); + self.wall_lines(stl, perimeter_verts, used_indices_sort, 2); + println!("----------------------------------"); @@ -357,6 +474,7 @@ impl Slicer for FFFSlicer { println!("{}", self.settings); println!("Generating layer heights"); let zs = self.layer_heights(&self.settings, &stl); + // println!("ZS: {:?}",self.layer_heights(sel)); let mut z_height: f32 = 0.0; // TODO must shift the stl up in the z direction, no negatives // let z_offset = -1.0 * -stl.bounding_box().z_min; diff --git a/src/slicer/mod.rs b/src/slicer/mod.rs index 5d35d16..4692a67 100644 --- a/src/slicer/mod.rs +++ b/src/slicer/mod.rs @@ -10,7 +10,7 @@ use crate::settings::{FloatOrVecOfFloats, Settings}; /// trait for shared behavior between slicers pub trait Slicer { fn layer_heights(&self, settings: &Settings, stl: &STLMesh) -> Vec { - let bb = stl.bounding_box(); + let bb = stl.outer_bounds();//stl.bounding_box(); let mut heights = vec![settings.layer_height.layer_0_height]; let total_height = bb.z_max - bb.z_min - heights[0];