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
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;
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)));
#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){
@ -1182,7 +1186,21 @@ PrintObject::check_nonplanar_collisions(NonplanarSurface &surface)
//collsion found abort when area > 1.0 mm²
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;
}
}
@ -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();
}
}
}
}

View File

@ -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;
}
}
}