From 33b9f37b0bda27c69b90c1bdad71ec2f69ed902e Mon Sep 17 00:00:00 2001 From: EiNSTeiN- Date: Sun, 2 Jul 2023 14:23:12 -0400 Subject: [PATCH] Somewhat improved collision detection --- src/libslic3r/PrintObject.cpp | 65 ++++++++++++++++++++---------- src/libslic3r/PrintObjectSlice.cpp | 37 ++++++++++++++--- 2 files changed, 75 insertions(+), 27 deletions(-) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 1877c34e4..9ac59af76 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1145,36 +1145,40 @@ void PrintObject::detect_surfaces_type() bool PrintObject::check_nonplanar_collisions(NonplanarSurface &surface) { + Polygons nonplanar_polygon = to_polygons(surface.horizontal_projection()); for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) { Polygons collider; - Polygons nonplanar_polygon = to_polygons(surface.horizontal_projection()); //check each layer for (size_t idx_layer = 0; idx_layer < m_layers.size(); ++ idx_layer) { m_print->throw_if_canceled(); - // BOOST_LOG_TRIVIAL(trace) << "Check nonplanar collisions for region " << region_id << " and layer " << layer->print_z; Layer *layer = m_layers[idx_layer]; LayerRegion *layerm = layer->m_regions[region_id]; - //skip if below minimum nonplanar surface - if (surface.stats.min.z-layer->height > layer->slice_z) continue; - //break if above nonplanar surface + // skip if below minimum nonplanar surface + if (surface.stats.min.z > layer->slice_z + layer->height) continue; + // break if above nonplanar surface if (surface.stats.max.z < layer->slice_z) break; - float angle_rad = m_config.nonplanar_layers_angle.value * 3.14159265/180.0; - float angle_offset = scale_(layer->height*std::sin(1.57079633-angle_rad)/std::sin(angle_rad)); + BOOST_LOG_TRIVIAL(trace) << "Check nonplanar collisions for region " << region_id << " and layer " << layer->print_z; - //debug - // SVG svg("svg/collider" + std::to_string(layer->id()) + ".svg"); - // svg.draw(layerm_slices_surfaces, "blue"); - // svg.draw(union_ex(diff(collider,nonplanar_polygon)), "red", 0.7f); - // svg.draw_outline(collider); - // svg.arrows = false; - // svg.Close(); + // float angle_rad = m_config.nonplanar_layers_angle.value * 3.14159265/180.0; + // float angle_offset = scale_(layer->height*std::sin(1.57079633-angle_rad)/std::sin(angle_rad)); //check if current surface collides with previous collider ExPolygons collisions = union_ex(intersection(layerm->slices().surfaces, diff(collider, nonplanar_polygon))); - if (!collisions.empty()){ +#ifdef SLIC3R_DEBUG_SLICE_PROCESSING + { + static int iRun = 0; + SVG svg(debug_out_path("Layer-%u-collider-%u_collisions_layer%.2f.svg", layer->id(), iRun++, layer->print_z), get_extents(layerm->slices().surfaces)); + svg.draw(layerm->slices().surfaces, "blue"); + svg.draw(collisions, "red", 0.7f); + svg.arrows = false; + svg.Close(); + } +#endif + + if (!collisions.empty()) { double area = 0; for (auto& c : collisions){ area += c.area(); @@ -1182,7 +1186,21 @@ PrintObject::check_nonplanar_collisions(NonplanarSurface &surface) //collsion found abort when area > 1.0 mm² if (1.0 < unscale(unscale(area))) { - std::cout << "Surface removed: collision on layer " << layer->print_z << "mm (" << unscale(unscale(area)) << " mm²)" << '\n'; + BOOST_LOG_TRIVIAL(trace) << "Surface removed: collision on layer " << layer->print_z << "mm (" << unscale(unscale(area)) << " mm²)"; + + //debug +#ifdef SLIC3R_DEBUG_SLICE_PROCESSING + { + static int iRun = 0; + SVG svg(debug_out_path("Layer-%u-collider-%u_removed_layer%.2f.svg", layer->id(), iRun++, layer->print_z), get_extents(layerm->slices().surfaces)); + svg.draw(layerm->slices().surfaces, "blue"); + svg.draw(union_ex(diff(collider,nonplanar_polygon)), "red", 0.7f); + svg.draw_outline(collider); + svg.arrows = false; + svg.Close(); + } +#endif + return true; } } @@ -1190,15 +1208,20 @@ PrintObject::check_nonplanar_collisions(NonplanarSurface &surface) if (layer->upper_layer != NULL) { Layer* upper_layer = layer->upper_layer; LayerRegion *upper_layerm = upper_layer->m_regions[region_id]; - //merge the ofsetted surface to the collider - collider= offset( - union_( + // merge surface to the collider + collider = union_( intersection( diff_ex(layerm->slices().surfaces, upper_layerm->slices().surfaces, ApplySafetyOffset::No), nonplanar_polygon, ApplySafetyOffset::No), - collider), - angle_offset); + collider); + + { + static int iRun = 0; + SVG svg(debug_out_path("Layer-%u-collider-%u_layer%.2f.svg", layer->id(), iRun++, layer->print_z), get_extents(layerm->slices().surfaces)); + svg.draw_outline(collider, "black", scale_(0.1f)); + svg.Close(); + } } } } diff --git a/src/libslic3r/PrintObjectSlice.cpp b/src/libslic3r/PrintObjectSlice.cpp index 74ddef783..75eaa3213 100644 --- a/src/libslic3r/PrintObjectSlice.cpp +++ b/src/libslic3r/PrintObjectSlice.cpp @@ -886,15 +886,36 @@ PrintObject::find_nonplanar_surfaces() // create nonplanar surface from facets NonplanarSurface nf = NonplanarSurface(facets); - BOOST_LOG_TRIVIAL(trace) << "Find nonplanar surfaces - moving surfaces by z=" << -tmesh.stats().min.z(); + BOOST_LOG_TRIVIAL(debug) << "Find nonplanar surfaces - moving surfaces by z=" << -tmesh.stats().min.z(); nf.translate(0, 0, -tmesh.stats().min.z()); // group surfaces and attach all nonplanar surfaces to the PrintObject m_nonplanar_surfaces = nf.group_surfaces(); +#ifdef SLIC3R_DEBUG_SLICE_PROCESSING + for (size_t id = 0; id < m_nonplanar_surfaces.size(); ++ id) { + auto& surface = m_nonplanar_surfaces[id]; + Surfaces surfaces; + surfaces_append(surfaces, surface.horizontal_projection(), SurfaceType::stTopNonplanar); + SurfaceCollection c(surfaces); + c.export_to_svg(debug_out_path("0_find_nonplanar_surface-%d-initial_layer%.2f.svg", id, surface.stats.min.z).c_str(), true); + } +#endif + + // check for surfaces that are actually flat + for (NonplanarSurfaces::iterator it = m_nonplanar_surfaces.begin(); it!=m_nonplanar_surfaces.end();) { + if((*it).stats.min.z == (*it).stats.max.z) { + BOOST_LOG_TRIVIAL(trace) << "Find nonplanar surfaces - deleted one surface with same min/max Z height"; + it = m_nonplanar_surfaces.erase(it); + } else { + it++; + } + } + // check if surfaces maintain maximum printing height, if not, erase it for (NonplanarSurfaces::iterator it = m_nonplanar_surfaces.begin(); it!=m_nonplanar_surfaces.end();) { if((*it).check_max_printing_height(m_config.nonplanar_layers_height.value)) { + BOOST_LOG_TRIVIAL(trace) << "Find nonplanar surfaces - deleted one surface due to max printing height constraint"; it = m_nonplanar_surfaces.erase(it); }else { it++; @@ -904,6 +925,7 @@ PrintObject::find_nonplanar_surfaces() // check if surfaces area is not too small for (NonplanarSurfaces::iterator it = m_nonplanar_surfaces.begin(); it!=m_nonplanar_surfaces.end();) { if((*it).check_surface_area()) { + BOOST_LOG_TRIVIAL(trace) << "Find nonplanar surfaces - deleted one surface due to print area too small"; it = m_nonplanar_surfaces.erase(it); }else { it++; @@ -913,6 +935,7 @@ PrintObject::find_nonplanar_surfaces() // check if surfaces areas collide for (NonplanarSurfaces::iterator it = m_nonplanar_surfaces.begin(); it!=m_nonplanar_surfaces.end();) { if(check_nonplanar_collisions((*it))) { + BOOST_LOG_TRIVIAL(trace) << "Find nonplanar surfaces - deleted one surface due to collision"; it = m_nonplanar_surfaces.erase(it); } else { it++; @@ -921,17 +944,19 @@ PrintObject::find_nonplanar_surfaces() //nf.debug_output(); -#ifdef SLIC3R_DEBUG_SLICE_PROCESSING + BOOST_LOG_TRIVIAL(info) << "Find nonplanar surfaces - found " << m_nonplanar_surfaces.size() << " in " << (*it)->name; + for (size_t id = 0; id < m_nonplanar_surfaces.size(); ++ id) { auto& surface = m_nonplanar_surfaces[id]; + BOOST_LOG_TRIVIAL(debug) << "Find nonplanar surfaces - surface" << id << " at Z [min=" << surface.stats.min.z << ", max=" << surface.stats.max.z << "]"; + +#ifdef SLIC3R_DEBUG_SLICE_PROCESSING Surfaces surfaces; surfaces_append(surfaces, surface.horizontal_projection(), SurfaceType::stTopNonplanar); SurfaceCollection c(surfaces); - c.export_to_svg(debug_out_path("0_find_nonplanar_surface-%d.svg", id).c_str(), true); - } + c.export_to_svg(debug_out_path("0_find_nonplanar_surface-%d-final_layer%.2f.svg", id, surface.stats.min.z).c_str(), true); #endif - - BOOST_LOG_TRIVIAL(info) << "Find nonplanar surfaces - found " << m_nonplanar_surfaces.size() << " in " << (*it)->name; + } } }