diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 179bd564c1..6390bfbaf4 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -6174,7 +6174,9 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill if (extrusions.empty()) return gcode; - chain_and_reorder_extrusion_entities(extrusions, m_last_pos.to_point()); + //ORCA: Respect no_sort to preserve support base outline->fill order. + if (!support_fills.no_sort) + chain_and_reorder_extrusion_entities(extrusions, m_last_pos.to_point()); const double support_speed = m_config.support_speed.value; const double support_interface_speed = m_config.get_abs_value("support_interface_speed"); diff --git a/src/libslic3r/Support/TreeSupport.cpp b/src/libslic3r/Support/TreeSupport.cpp index aaf3ba4443..6f77c4a77b 100644 --- a/src/libslic3r/Support/TreeSupport.cpp +++ b/src/libslic3r/Support/TreeSupport.cpp @@ -1610,80 +1610,71 @@ void TreeSupport::generate_toolpaths() filler_support->angle = Geometry::deg2rad(object_config.support_angle.value); Polygons loops = to_polygons(poly); + //ORCA: Group base per area as no_sort to keep outline->fill together. + std::unique_ptr base_eec = std::make_unique(); + base_eec->no_sort = true; + ExtrusionEntitiesPtr &base_dst = base_eec->entities; if (layer_id == 0) { float density = float(m_object_config->raft_first_layer_density.value * 0.01); - fill_expolygons_with_sheath_generate_paths(ts_layer->support_fills.entities, loops, filler_support.get(), density, erSupportMaterial, flow, + fill_expolygons_with_sheath_generate_paths(base_dst, loops, filler_support.get(), density, erSupportMaterial, flow, m_support_params, true, false); } else { + //ORCA: Force base walls before infill to keep outline->fill order. if (need_infill && m_support_params.base_fill_pattern != ipLightning) { // allow infill-only mode if support is thick enough (so min_wall_count is 0); // otherwise must draw 1 wall // Don't need extra walls if we have infill. Extra walls may overlap with the infills. size_t min_wall_count = offset(poly, -scale_(support_spacing * 1.5)).empty() ? 1 : 0; - make_perimeter_and_infill(ts_layer->support_fills.entities, poly, std::max(min_wall_count, wall_count), flow, - erSupportMaterial, filler_support.get(), support_density); + make_perimeter_and_infill(base_dst, poly, std::max(min_wall_count, wall_count), flow, + erSupportMaterial, filler_support.get(), support_density, false); } else { SupportParameters support_params = m_support_params; if (area_group.need_extra_wall && object_config.tree_support_wall_count.value == 0) support_params.tree_branch_diameter_double_wall_area_scaled = 0.1; - tree_supports_generate_paths(ts_layer->support_fills.entities, loops, flow, support_params); + tree_supports_generate_paths(base_dst, loops, flow, support_params); } } - } - } - if (m_support_params.base_fill_pattern == ipLightning) - { - double print_z = ts_layer->print_z; - if (printZ_to_lightninglayer.find(print_z) == printZ_to_lightninglayer.end()) - continue; - //TODO: - //1.the second parameter of convertToLines seems to decide how long the lightning should be trimmed from its root, so that the root wont overlap/detach the support contour. - // whether current value works correctly remained to be tested - //2.related to previous one, that lightning roots need to be trimed more when support has multiple walls - //3.function connect_infill() and variable 'params' helps create connection pattern along contours between two lightning roots, - // strengthen lightnings while it may make support harder. decide to enable it or not. if yes, proper values for params are remained to be tested - auto& lightning_layer = generator->getTreesForLayer(printZ_to_lightninglayer[print_z]); - - Flow flow = (layer_id == 0 && m_raft_layers == 0) ? m_support_params.first_layer_flow : support_flow; - ExPolygons areas = offset_ex(ts_layer->base_areas, -flow.scaled_spacing()); - - for (auto& area : areas) - { - Polylines polylines = lightning_layer.convertToLines(to_polygons(area), 0); - for (auto itr = polylines.begin(); itr != polylines.end();) - { - if (itr->length() < scale_(1.0)) - itr = polylines.erase(itr); - else - itr++; - } - Polylines opt_polylines; -#if 1 - //this wont create connection patterns along contours - append(opt_polylines, chain_polylines(std::move(polylines))); -#else - //this will create connection patterns along contours - FillParams params; - params.anchor_length = float(Fill::infill_anchor * 0.01 * flow.spacing()); - params.anchor_length_max = Fill::infill_anchor_max; - params.anchor_length = std::min(params.anchor_length, params.anchor_length_max); - Fill::connect_infill(std::move(polylines), area, opt_polylines, flow.spacing(), params); -#endif - extrusion_entities_append_paths(ts_layer->support_fills.entities, opt_polylines, erSupportMaterial, - float(flow.mm3_per_mm()), float(flow.width()), float(flow.height())); + //ORCA: Emit lightning infill per base area to avoid interleaving across islands. + if (m_support_params.base_fill_pattern == ipLightning) { + double print_z = ts_layer->print_z; + auto lightning_layer_mapping = printZ_to_lightninglayer.find(print_z); + if (lightning_layer_mapping != printZ_to_lightninglayer.end()) { + auto &lightning_layer = generator->getTreesForLayer(lightning_layer_mapping->second); + ExPolygons areas; + areas.emplace_back(poly); + areas = offset_ex(areas, -flow.scaled_spacing()); + for (auto &area : areas) { + Polylines polylines = lightning_layer.convertToLines(to_polygons(area), 0); + for (auto itr = polylines.begin(); itr != polylines.end();) { + if (itr->length() < scale_(1.0)) + itr = polylines.erase(itr); + else + itr++; + } + Polylines opt_polylines; + append(opt_polylines, chain_polylines(std::move(polylines))); + extrusion_entities_append_paths(base_dst, opt_polylines, erSupportMaterial, + float(flow.mm3_per_mm()), float(flow.width()), float(flow.height())); #ifdef SUPPORT_TREE_DEBUG_TO_SVG - std::string name = debug_out_path("trees_polyline_%.2f.svg", ts_layer->print_z); - BoundingBox bbox = get_extents(ts_layer->base_areas); - SVG svg(name, bbox); - if (svg.is_opened()) { - svg.draw(ts_layer->base_areas, "blue"); - svg.draw(generator->Overhangs()[printZ_to_lightninglayer[print_z]], "red"); - for (auto &line : opt_polylines) svg.draw(line, "yellow"); - } + std::string name = debug_out_path("trees_polyline_%.2f.svg", ts_layer->print_z); + BoundingBox bbox = get_extents(ts_layer->base_areas); + SVG svg(name, bbox); + if (svg.is_opened()) { + svg.draw(ts_layer->base_areas, "blue"); + svg.draw(generator->Overhangs()[lightning_layer_mapping->second], "red"); + for (auto &line : opt_polylines) svg.draw(line, "yellow"); + } #endif + } + } + } + + //ORCA: Keep per-area base paths grouped for outline->fill preservation. + if (!base_eec->empty()) + ts_layer->support_fills.entities.push_back(base_eec.release()); } }