diff --git a/src/libslic3r/TreeModelVolumes.cpp b/src/libslic3r/TreeModelVolumes.cpp index f29193dbfd..db12724aea 100644 --- a/src/libslic3r/TreeModelVolumes.cpp +++ b/src/libslic3r/TreeModelVolumes.cpp @@ -520,14 +520,54 @@ void TreeModelVolumes::calculateCollision(const coord_t radius, const LayerIndex // 2) Sum over top / bottom ranges. const bool last = outline_idx == layer_outline_indices.size(); tbb::parallel_for(tbb::blocked_range(min_layer_last + 1, max_layer_idx + 1), - [&collision_areas_offsetted, &anti_overhang = m_anti_overhang, min_layer_bottom, radius, z_distance_bottom_layers, z_distance_top_layers, min_resolution = m_min_resolution, &data, min_layer_last, last, &throw_on_cancel] + [&collision_areas_offsetted, &outlines, &machine_border = m_machine_border, &anti_overhang = m_anti_overhang, min_layer_bottom, radius, + xy_distance, z_distance_bottom_layers, z_distance_top_layers, min_resolution = m_min_resolution, &data, min_layer_last, last, &throw_on_cancel] (const tbb::blocked_range& range) { for (LayerIndex layer_idx = range.begin(); layer_idx != range.end(); ++layer_idx) { Polygons collisions; for (int i = -z_distance_bottom_layers; i <= z_distance_top_layers; ++ i) { int j = layer_idx + i - min_layer_bottom; - if (j >= 0 && j < int(collision_areas_offsetted.size())) + if (j >= 0 && j < int(collision_areas_offsetted.size()) && i <= 0) append(collisions, collision_areas_offsetted[j]); + else if (j >= 0 && layer_idx + i < int(outlines.size()) && i > 0) { + Polygons collision_areas_original = machine_border; + append(collision_areas_original, outlines[layer_idx + i]); + + // If just the collision (including the xy distance) of the layers above is accumulated, it leads to the + // following issue: + // Example: assuming the z distance is 2 layer + // + = xy_distance + // - = model + // o = overhang of the area two layers above that should result in tips on this layer + // + // +-----+ + // +-----+ + // +-----+ + // o +-----+ + // If just the collision above is accumulated the overhang will get overwritten by the xy_distance of the + // layer below the overhang... + // + // This only causes issues if the overhang area is thinner than xy_distance + // Just accumulating areas of the model above without the xy distance is also problematic, as then support + // may get closer to the model (on the diagonal downwards) than the user intended. Example (s = support): + // +-----+ + // +-----+ + // +-----+ + // s+-----+ + + // technically the calculation below is off by one layer, as the actual distance between plastic one layer + // down is 0 not layer height, as this layer is filled with said plastic. But otherwise a part of the + // overhang that is expected to be supported is overwritten by the remaining part of the xy distance of the + // layer below the to be supported area. + coord_t required_range_x = + (xy_distance - ((i - (z_distance_top_layers == 1 ? 0.5 : 0)) * xy_distance / z_distance_top_layers)); + // the conditional -0.5 ensures that plastic can never touch on the diagonal + // downward when the z_distance_top_layers = 1. It is assumed to be better to + // not support an overhang<90 degree than to risk fusing to it. + + collision_areas_original = offset(union_ex(collision_areas_original), radius + required_range_x, ClipperLib::jtMiter, 1.2); + append(collisions, collision_areas_original); + } } collisions = last && layer_idx < int(anti_overhang.size()) ? union_(collisions, offset(union_ex(anti_overhang[layer_idx]), radius, ClipperLib::jtMiter, 1.2)) : union_(collisions); auto &dst = data[layer_idx - (min_layer_last + 1)]; @@ -644,6 +684,8 @@ void TreeModelVolumes::calculateAvoidance(const std::vector &ke BOOST_LOG_TRIVIAL(debug) << "Calculation requested for value already calculated?"; continue; } + if ((task.to_model && !to_model) || (!task.to_model && !to_build_plate)) + continue; if (! task.holefree() || task.radius < m_increase_until_radius + m_current_min_xy_dist_delta) avoidance_tasks.emplace_back(task); } diff --git a/src/libslic3r/TreeSupport.cpp b/src/libslic3r/TreeSupport.cpp index 00eec7df0c..67d76f2185 100644 --- a/src/libslic3r/TreeSupport.cpp +++ b/src/libslic3r/TreeSupport.cpp @@ -576,7 +576,8 @@ static std::optional> polyline_sample_next_point_at_dis double next_distance = current_distance; // Get points so that at least min_points are added and they each are current_distance away from each other. If that is impossible, decrease current_distance a bit. // The input are lines, that means that the line from the last to the first vertex does not have to exist, so exclude all points that are on this line! - while ((next_point = polyline_sample_next_point_at_distance(part.points, current_point, current_index, next_distance))) { + while ((next_point = polyline_sample_next_point_at_distance(part.points, current_point, current_index, next_distance)) && + next_point->second < coord_t(part.size()) - 1) { // Not every point that is distance away, is valid, as it may be much closer to another point. This is especially the case when the overhang is very thin. // So this ensures that the points are actually a certain distance from each other. // This assurance is only made on a per polygon basis, as different but close polygon may not be able to use support below the other polygon. @@ -916,7 +917,7 @@ static void generate_initial_areas( //FIXME Vojtech: This is not sufficient for support enforcers to work. //FIXME There is no account for the support overhang angle. //FIXME There is no account for the width of the collision regions. - const coord_t extra_outset = std::max(coord_t(0), mesh_config.min_radius - mesh_config.support_line_width) + (min_xy_dist ? mesh_config.support_line_width / 2 : 0) + const coord_t extra_outset = std::max(coord_t(0), mesh_config.min_radius - mesh_config.support_line_width / 2) + (min_xy_dist ? mesh_config.support_line_width / 2 : 0) //FIXME this is a heuristic value for support enforcers to work. // + 10 * mesh_config.support_line_width; ; @@ -1079,9 +1080,8 @@ static void generate_initial_areas( Polygons overhang_regular; { const Polygons &overhang_raw = overhangs[layer_idx + z_distance_delta]; - overhang_regular = mesh_group_settings.support_offset == 0 ? - overhang_raw : - safe_offset_inc(overhang_raw, mesh_group_settings.support_offset, relevant_forbidden, mesh_config.min_radius * 1.75 + mesh_config.xy_min_distance, 0, 1); + // When support_offset = 0 safe_offset_inc will only be the difference between overhang_raw and relevant_forbidden, that has to be calculated anyway. + overhang_regular = safe_offset_inc(overhang_raw, mesh_group_settings.support_offset, relevant_forbidden, mesh_config.min_radius * 1.75 + mesh_config.xy_min_distance, 0, 1); //check_self_intersections(overhang_regular, "overhang_regular1"); // offset ensures that areas that could be supported by a part of a support line, are not considered unsupported overhang