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())
|
||||
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");
|
||||
|
||||
@@ -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<ExtrusionEntityCollection> base_eec = std::make_unique<ExtrusionEntityCollection>();
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user