diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index d836ac43c..1ddee6b7c 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -3134,15 +3134,26 @@ bool GCode::needs_retraction(const Polyline &travel, ExtrusionRole role) return false; } - if (role == erSupportMaterial) { - const SupportLayer* support_layer = dynamic_cast(m_layer); - //FIXME support_layer->support_islands.contains should use some search structure! - if (support_layer != NULL && ! intersection_pl(travel, support_layer->support_islands).empty()) - // skip retraction if this is a travel move inside a support material island - //FIXME not retracting over a long path may cause oozing, which in turn may result in missing material - // at the end of the extrusion path! - return false; - } + if (role == erSupportMaterial) + if (const SupportLayer *support_layer = dynamic_cast(m_layer); + support_layer != nullptr && ! support_layer->support_islands_bboxes.empty()) { + BoundingBox bbox_travel = get_extents(travel); + Polylines trimmed; + bool trimmed_initialized = false; + for (const BoundingBox &bbox : support_layer->support_islands_bboxes) + if (bbox.overlap(bbox_travel)) { + const auto &island = support_layer->support_islands[&bbox - support_layer->support_islands_bboxes.data()]; + trimmed = trimmed_initialized ? diff_pl(trimmed, island) : diff_pl(travel, island); + trimmed_initialized = true; + if (trimmed.empty()) + // skip retraction if this is a travel move inside a support material island + //FIXME not retracting over a long path may cause oozing, which in turn may result in missing material + // at the end of the extrusion path! + return false; + // Not sure whether updating the boudning box isn't too expensive. + //bbox_travel = get_extents(trimmed); + } + } if (m_config.only_retract_when_crossing_perimeters && m_layer != nullptr && m_config.fill_density.value > 0 && m_layer->any_internal_region_slice_contains(travel)) diff --git a/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp index 21de030cd..e11c740e6 100644 --- a/src/libslic3r/Layer.hpp +++ b/src/libslic3r/Layer.hpp @@ -197,6 +197,8 @@ public: // Polygons covered by the supports: base, interface and contact areas. // Used to suppress retraction if moving for a support extrusion over these support_islands. ExPolygons support_islands; + // Slightly inflated bounding boxes of the above, for faster intersection query. + std::vector support_islands_bboxes; // Extrusion paths for the support base and for the support interface and contacts. ExtrusionEntityCollection support_fills; diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index 340449ec8..0f704c3d6 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -4312,8 +4312,13 @@ void generate_support_toolpaths( // Order the layers by lexicographically by an increasing print_z and a decreasing layer height. std::stable_sort(layer_cache_item.overlapping.begin(), layer_cache_item.overlapping.end(), [](auto *l1, auto *l2) { return *l1 < *l2; }); } - if (! polys.empty()) - expolygons_append(support_layer.support_islands, union_ex(polys)); + assert(support_layer.support_islands.empty()); + if (! polys.empty()) { + support_layer.support_islands = union_ex(polys); + support_layer.support_islands_bboxes.reserve(support_layer.support_islands.size()); + for (const ExPolygon &expoly : support_layer.support_islands) + support_layer.support_islands_bboxes.emplace_back(get_extents(expoly).inflated(SCALED_EPSILON)); + } } // for each support_layer_id });