Fix xy_distance overriding overhangs when the overhang angle is smallish

This commit is contained in:
Thomas Rahm 2022-12-20 23:09:06 +01:00
parent e87dcffff1
commit a81f6703d9

View File

@ -494,14 +494,53 @@ void TreeModelVolumes::calculateCollision(const coord_t radius, const LayerIndex
// 2) Sum over top / bottom ranges. // 2) Sum over top / bottom ranges.
const bool last = outline_idx == layer_outline_indices.size(); const bool last = outline_idx == layer_outline_indices.size();
tbb::parallel_for(tbb::blocked_range<LayerIndex>(min_layer_last + 1, max_layer_idx + 1), tbb::parallel_for(tbb::blocked_range<LayerIndex>(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] [&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]
(const tbb::blocked_range<LayerIndex>& range) { (const tbb::blocked_range<LayerIndex>& range) {
for (LayerIndex layer_idx = range.begin(); layer_idx != range.end(); ++layer_idx) { for (LayerIndex layer_idx = range.begin(); layer_idx != range.end(); ++layer_idx) {
Polygons collisions; Polygons collisions;
for (int i = -z_distance_bottom_layers; i <= z_distance_top_layers; ++ i) { for (int i = -z_distance_bottom_layers; i <= z_distance_top_layers; ++ i) {
int j = layer_idx + i - min_layer_bottom; 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]); 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); 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)]; auto &dst = data[layer_idx - (min_layer_last + 1)];