Somewhat improved collision detection

This commit is contained in:
EiNSTeiN- 2023-07-02 14:23:12 -04:00
parent b6ec5be295
commit 33b9f37b0b
2 changed files with 75 additions and 27 deletions

View File

@ -1145,35 +1145,39 @@ void PrintObject::detect_surfaces_type()
bool bool
PrintObject::check_nonplanar_collisions(NonplanarSurface &surface) 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) { for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) {
Polygons collider; Polygons collider;
Polygons nonplanar_polygon = to_polygons(surface.horizontal_projection());
//check each layer //check each layer
for (size_t idx_layer = 0; idx_layer < m_layers.size(); ++ idx_layer) { for (size_t idx_layer = 0; idx_layer < m_layers.size(); ++ idx_layer) {
m_print->throw_if_canceled(); 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]; Layer *layer = m_layers[idx_layer];
LayerRegion *layerm = layer->m_regions[region_id]; LayerRegion *layerm = layer->m_regions[region_id];
// skip if below minimum nonplanar surface // skip if below minimum nonplanar surface
if (surface.stats.min.z-layer->height > layer->slice_z) continue; if (surface.stats.min.z > layer->slice_z + layer->height) continue;
// break if above nonplanar surface // break if above nonplanar surface
if (surface.stats.max.z < layer->slice_z) break; if (surface.stats.max.z < layer->slice_z) break;
float angle_rad = m_config.nonplanar_layers_angle.value * 3.14159265/180.0; BOOST_LOG_TRIVIAL(trace) << "Check nonplanar collisions for region " << region_id << " and layer " << layer->print_z;
float angle_offset = scale_(layer->height*std::sin(1.57079633-angle_rad)/std::sin(angle_rad));
//debug // float angle_rad = m_config.nonplanar_layers_angle.value * 3.14159265/180.0;
// SVG svg("svg/collider" + std::to_string(layer->id()) + ".svg"); // float angle_offset = scale_(layer->height*std::sin(1.57079633-angle_rad)/std::sin(angle_rad));
// 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();
//check if current surface collides with previous collider //check if current surface collides with previous collider
ExPolygons collisions = union_ex(intersection(layerm->slices().surfaces, diff(collider, nonplanar_polygon))); ExPolygons collisions = union_ex(intersection(layerm->slices().surfaces, diff(collider, nonplanar_polygon)));
#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()) { if (!collisions.empty()) {
double area = 0; double area = 0;
for (auto& c : collisions){ for (auto& c : collisions){
@ -1182,7 +1186,21 @@ PrintObject::check_nonplanar_collisions(NonplanarSurface &surface)
//collsion found abort when area > 1.0 mm² //collsion found abort when area > 1.0 mm²
if (1.0 < unscale<double>(unscale<double>(area))) { if (1.0 < unscale<double>(unscale<double>(area))) {
std::cout << "Surface removed: collision on layer " << layer->print_z << "mm (" << unscale<double>(unscale<double>(area)) << " mm²)" << '\n'; BOOST_LOG_TRIVIAL(trace) << "Surface removed: collision on layer " << layer->print_z << "mm (" << unscale<double>(unscale<double>(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; return true;
} }
} }
@ -1190,15 +1208,20 @@ PrintObject::check_nonplanar_collisions(NonplanarSurface &surface)
if (layer->upper_layer != NULL) { if (layer->upper_layer != NULL) {
Layer* upper_layer = layer->upper_layer; Layer* upper_layer = layer->upper_layer;
LayerRegion *upper_layerm = upper_layer->m_regions[region_id]; LayerRegion *upper_layerm = upper_layer->m_regions[region_id];
//merge the ofsetted surface to the collider // merge surface to the collider
collider= offset( collider = union_(
union_(
intersection( intersection(
diff_ex(layerm->slices().surfaces, upper_layerm->slices().surfaces, ApplySafetyOffset::No), diff_ex(layerm->slices().surfaces, upper_layerm->slices().surfaces, ApplySafetyOffset::No),
nonplanar_polygon, nonplanar_polygon,
ApplySafetyOffset::No), ApplySafetyOffset::No),
collider), collider);
angle_offset);
{
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();
}
} }
} }
} }

View File

@ -886,15 +886,36 @@ PrintObject::find_nonplanar_surfaces()
// create nonplanar surface from facets // create nonplanar surface from facets
NonplanarSurface nf = NonplanarSurface(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()); nf.translate(0, 0, -tmesh.stats().min.z());
// group surfaces and attach all nonplanar surfaces to the PrintObject // group surfaces and attach all nonplanar surfaces to the PrintObject
m_nonplanar_surfaces = nf.group_surfaces(); 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 // check if surfaces maintain maximum printing height, if not, erase it
for (NonplanarSurfaces::iterator it = m_nonplanar_surfaces.begin(); it!=m_nonplanar_surfaces.end();) { 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)) { 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); it = m_nonplanar_surfaces.erase(it);
}else { }else {
it++; it++;
@ -904,6 +925,7 @@ PrintObject::find_nonplanar_surfaces()
// check if surfaces area is not too small // check if surfaces area is not too small
for (NonplanarSurfaces::iterator it = m_nonplanar_surfaces.begin(); it!=m_nonplanar_surfaces.end();) { for (NonplanarSurfaces::iterator it = m_nonplanar_surfaces.begin(); it!=m_nonplanar_surfaces.end();) {
if((*it).check_surface_area()) { 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); it = m_nonplanar_surfaces.erase(it);
}else { }else {
it++; it++;
@ -913,6 +935,7 @@ PrintObject::find_nonplanar_surfaces()
// check if surfaces areas collide // check if surfaces areas collide
for (NonplanarSurfaces::iterator it = m_nonplanar_surfaces.begin(); it!=m_nonplanar_surfaces.end();) { for (NonplanarSurfaces::iterator it = m_nonplanar_surfaces.begin(); it!=m_nonplanar_surfaces.end();) {
if(check_nonplanar_collisions((*it))) { if(check_nonplanar_collisions((*it))) {
BOOST_LOG_TRIVIAL(trace) << "Find nonplanar surfaces - deleted one surface due to collision";
it = m_nonplanar_surfaces.erase(it); it = m_nonplanar_surfaces.erase(it);
} else { } else {
it++; it++;
@ -921,17 +944,19 @@ PrintObject::find_nonplanar_surfaces()
//nf.debug_output(); //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) { for (size_t id = 0; id < m_nonplanar_surfaces.size(); ++ id) {
auto& surface = m_nonplanar_surfaces[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 surfaces;
surfaces_append(surfaces, surface.horizontal_projection(), SurfaceType::stTopNonplanar); surfaces_append(surfaces, surface.horizontal_projection(), SurfaceType::stTopNonplanar);
SurfaceCollection c(surfaces); 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 #endif
}
BOOST_LOG_TRIVIAL(info) << "Find nonplanar surfaces - found " << m_nonplanar_surfaces.size() << " in " << (*it)->name;
} }
} }