mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-09 18:27:00 +00:00
Fix inconsistent ordering of support base outline and fill (#11761)
* Preserve support base outline/fill order Honor no_sort when emitting support toolpaths to keep outline-first order. Group tree support base paths (including lightning) into per-area no_sort collections to prevent interleaving across islands. Keep lightning layer lookup side-effect free. * Tag Orca specific changes Tag Orca specific changes vs. Bambu using the comment //ORCA: . This helps when reviewing merge commits from upstream Bambu so we don't end up causing regressions when pulling in commits from upstream
This commit is contained in:
@@ -6174,7 +6174,9 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill
|
|||||||
if (extrusions.empty())
|
if (extrusions.empty())
|
||||||
return gcode;
|
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_speed = m_config.support_speed.value;
|
||||||
const double support_interface_speed = m_config.get_abs_value("support_interface_speed");
|
const double support_interface_speed = m_config.get_abs_value("support_interface_speed");
|
||||||
|
|||||||
@@ -1610,80 +1610,71 @@ void TreeSupport::generate_toolpaths()
|
|||||||
filler_support->angle = Geometry::deg2rad(object_config.support_angle.value);
|
filler_support->angle = Geometry::deg2rad(object_config.support_angle.value);
|
||||||
|
|
||||||
Polygons loops = to_polygons(poly);
|
Polygons loops = to_polygons(poly);
|
||||||
|
//ORCA: Group base per area as no_sort to keep outline->fill together.
|
||||||
|
std::unique_ptr<ExtrusionEntityCollection> base_eec = std::make_unique<ExtrusionEntityCollection>();
|
||||||
|
base_eec->no_sort = true;
|
||||||
|
ExtrusionEntitiesPtr &base_dst = base_eec->entities;
|
||||||
if (layer_id == 0) {
|
if (layer_id == 0) {
|
||||||
float density = float(m_object_config->raft_first_layer_density.value * 0.01);
|
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);
|
m_support_params, true, false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
//ORCA: Force base walls before infill to keep outline->fill order.
|
||||||
if (need_infill && m_support_params.base_fill_pattern != ipLightning) {
|
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);
|
// allow infill-only mode if support is thick enough (so min_wall_count is 0);
|
||||||
// otherwise must draw 1 wall
|
// otherwise must draw 1 wall
|
||||||
// Don't need extra walls if we have infill. Extra walls may overlap with the infills.
|
// 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;
|
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,
|
make_perimeter_and_infill(base_dst, poly, std::max(min_wall_count, wall_count), flow,
|
||||||
erSupportMaterial, filler_support.get(), support_density);
|
erSupportMaterial, filler_support.get(), support_density, false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
SupportParameters support_params = m_support_params;
|
SupportParameters support_params = m_support_params;
|
||||||
if (area_group.need_extra_wall && object_config.tree_support_wall_count.value == 0)
|
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;
|
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
|
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
||||||
std::string name = debug_out_path("trees_polyline_%.2f.svg", ts_layer->print_z);
|
std::string name = debug_out_path("trees_polyline_%.2f.svg", ts_layer->print_z);
|
||||||
BoundingBox bbox = get_extents(ts_layer->base_areas);
|
BoundingBox bbox = get_extents(ts_layer->base_areas);
|
||||||
SVG svg(name, bbox);
|
SVG svg(name, bbox);
|
||||||
if (svg.is_opened()) {
|
if (svg.is_opened()) {
|
||||||
svg.draw(ts_layer->base_areas, "blue");
|
svg.draw(ts_layer->base_areas, "blue");
|
||||||
svg.draw(generator->Overhangs()[printZ_to_lightninglayer[print_z]], "red");
|
svg.draw(generator->Overhangs()[lightning_layer_mapping->second], "red");
|
||||||
for (auto &line : opt_polylines) svg.draw(line, "yellow");
|
for (auto &line : opt_polylines) svg.draw(line, "yellow");
|
||||||
}
|
}
|
||||||
#endif
|
#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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user