Organic Supports improvements:
Added support_tree_branch_distance parameter to UI Fixed error in calculation of placeable areas, which made some trees to cut through an object. Locked the tree tips against smoothing of their centerline path. Reduced density of tips with zero interface layers (see continuous_tips). Reduced default support_tree_top_rate to 15% Refactored placement of interfaces for readability.
This commit is contained in:
parent
ca0b218a56
commit
9ce81d6d12
@ -452,7 +452,7 @@ static std::vector<std::string> s_Preset_print_options {
|
|||||||
"support_material_interface_pattern", "support_material_interface_spacing", "support_material_interface_contact_loops",
|
"support_material_interface_pattern", "support_material_interface_spacing", "support_material_interface_contact_loops",
|
||||||
"support_material_contact_distance", "support_material_bottom_contact_distance",
|
"support_material_contact_distance", "support_material_bottom_contact_distance",
|
||||||
"support_material_buildplate_only",
|
"support_material_buildplate_only",
|
||||||
"support_tree_angle", "support_tree_angle_slow", "support_tree_branch_diameter", "support_tree_branch_diameter_angle", "support_tree_top_rate", "support_tree_tip_diameter",
|
"support_tree_angle", "support_tree_angle_slow", "support_tree_branch_diameter", "support_tree_branch_diameter_angle", "support_tree_top_rate", "support_tree_branch_distance", "support_tree_tip_diameter",
|
||||||
"dont_support_bridges", "thick_bridges", "notes", "complete_objects", "extruder_clearance_radius",
|
"dont_support_bridges", "thick_bridges", "notes", "complete_objects", "extruder_clearance_radius",
|
||||||
"extruder_clearance_height", "gcode_comments", "gcode_label_objects", "output_filename_format", "post_process", "gcode_substitutions", "perimeter_extruder",
|
"extruder_clearance_height", "gcode_comments", "gcode_label_objects", "output_filename_format", "post_process", "gcode_substitutions", "perimeter_extruder",
|
||||||
"infill_extruder", "solid_infill_extruder", "support_material_extruder", "support_material_interface_extruder",
|
"infill_extruder", "solid_infill_extruder", "support_material_extruder", "support_material_interface_extruder",
|
||||||
|
@ -2910,6 +2910,18 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionFloat(5));
|
def->set_default_value(new ConfigOptionFloat(5));
|
||||||
|
|
||||||
|
// Tree Support Branch Distance
|
||||||
|
// How far apart the branches need to be when they touch the model. Making this distance small will cause
|
||||||
|
// the tree support to touch the model at more points, causing better overhang but making support harder to remove.
|
||||||
|
def = this->add("support_tree_branch_distance", coFloat);
|
||||||
|
def->label = L("Branch Distance");
|
||||||
|
def->category = L("Support material");
|
||||||
|
def->tooltip = L("How far apart the branches need to be when they touch the model. "
|
||||||
|
"Making this distance small will cause the tree support to touch the model at more points, "
|
||||||
|
"causing better overhang but making support harder to remove.");
|
||||||
|
def->mode = comAdvanced;
|
||||||
|
def->set_default_value(new ConfigOptionFloat(1.));
|
||||||
|
|
||||||
def = this->add("support_tree_top_rate", coPercent);
|
def = this->add("support_tree_top_rate", coPercent);
|
||||||
def->label = L("Branch Density");
|
def->label = L("Branch Density");
|
||||||
def->category = L("Support material");
|
def->category = L("Support material");
|
||||||
@ -2921,7 +2933,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->min = 5;
|
def->min = 5;
|
||||||
def->max_literal = 35;
|
def->max_literal = 35;
|
||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionPercent(30));
|
def->set_default_value(new ConfigOptionPercent(15));
|
||||||
|
|
||||||
def = this->add("temperature", coInts);
|
def = this->add("temperature", coInts);
|
||||||
def->label = L("Other layers");
|
def->label = L("Other layers");
|
||||||
|
@ -555,6 +555,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||||||
((ConfigOptionFloat, support_tree_branch_diameter))
|
((ConfigOptionFloat, support_tree_branch_diameter))
|
||||||
((ConfigOptionFloat, support_tree_branch_diameter_angle))
|
((ConfigOptionFloat, support_tree_branch_diameter_angle))
|
||||||
((ConfigOptionPercent, support_tree_top_rate))
|
((ConfigOptionPercent, support_tree_top_rate))
|
||||||
|
((ConfigOptionFloat, support_tree_branch_distance))
|
||||||
((ConfigOptionFloat, support_tree_tip_diameter))
|
((ConfigOptionFloat, support_tree_tip_diameter))
|
||||||
// The rest
|
// The rest
|
||||||
((ConfigOptionBool, thick_bridges))
|
((ConfigOptionBool, thick_bridges))
|
||||||
|
@ -693,6 +693,7 @@ bool PrintObject::invalidate_state_by_config_options(
|
|||||||
|| opt_key == "support_tree_branch_diameter"
|
|| opt_key == "support_tree_branch_diameter"
|
||||||
|| opt_key == "support_tree_branch_diameter_angle"
|
|| opt_key == "support_tree_branch_diameter_angle"
|
||||||
|| opt_key == "support_tree_top_rate"
|
|| opt_key == "support_tree_top_rate"
|
||||||
|
|| opt_key == "support_tree_branch_distance"
|
||||||
|| opt_key == "support_tree_tip_diameter"
|
|| opt_key == "support_tree_tip_diameter"
|
||||||
|| opt_key == "raft_expansion"
|
|| opt_key == "raft_expansion"
|
||||||
|| opt_key == "raft_first_layer_density"
|
|| opt_key == "raft_first_layer_density"
|
||||||
|
@ -89,7 +89,7 @@ TreeSupportMeshGroupSettings::TreeSupportMeshGroupSettings(const PrintObject &pr
|
|||||||
// this->minimum_support_area =
|
// this->minimum_support_area =
|
||||||
// this->minimum_bottom_area =
|
// this->minimum_bottom_area =
|
||||||
// this->support_offset =
|
// this->support_offset =
|
||||||
// this->support_tree_branch_distance = 2.5 * line_width ??
|
this->support_tree_branch_distance = scaled<coord_t>(config.support_tree_branch_distance.value);
|
||||||
this->support_tree_angle = std::clamp<double>(config.support_tree_angle * M_PI / 180., 0., 0.5 * M_PI - EPSILON);
|
this->support_tree_angle = std::clamp<double>(config.support_tree_angle * M_PI / 180., 0., 0.5 * M_PI - EPSILON);
|
||||||
this->support_tree_angle_slow = std::clamp<double>(config.support_tree_angle_slow * M_PI / 180., 0., this->support_tree_angle - EPSILON);
|
this->support_tree_angle_slow = std::clamp<double>(config.support_tree_angle_slow * M_PI / 180., 0., this->support_tree_angle - EPSILON);
|
||||||
this->support_tree_branch_diameter = scaled<coord_t>(config.support_tree_branch_diameter.value);
|
this->support_tree_branch_diameter = scaled<coord_t>(config.support_tree_branch_diameter.value);
|
||||||
@ -329,6 +329,7 @@ void TreeModelVolumes::precalculate(const PrintObject& print_object, const coord
|
|||||||
for (int k = int(j - 1); k >= int(i); -- k) {
|
for (int k = int(j - 1); k >= int(i); -- k) {
|
||||||
std::string legend = format("radius-%1%", unscaled<float>(sorted[k].first.first));
|
std::string legend = format("radius-%1%", unscaled<float>(sorted[k].first.first));
|
||||||
expolygons_with_attributes.push_back({ union_ex(sorted[k].second), SVG::ExPolygonAttributes(legend, std::string(colors[(k - int(i)) % num_colors]), 1.) });
|
expolygons_with_attributes.push_back({ union_ex(sorted[k].second), SVG::ExPolygonAttributes(legend, std::string(colors[(k - int(i)) % num_colors]), 1.) });
|
||||||
|
SVG::export_expolygons(debug_out_path("treesupport_cache-%s-%d-%s.svg", name.data(), sorted[i].first.second, legend.c_str()), { expolygons_with_attributes.back() });
|
||||||
}
|
}
|
||||||
// Render the range of per radius collision polygons into a common SVG.
|
// Render the range of per radius collision polygons into a common SVG.
|
||||||
SVG::export_expolygons(debug_out_path("treesupport_cache-%s-%d.svg", name.data(), sorted[i].first.second), expolygons_with_attributes);
|
SVG::export_expolygons(debug_out_path("treesupport_cache-%s-%d.svg", name.data(), sorted[i].first.second), expolygons_with_attributes);
|
||||||
@ -416,9 +417,6 @@ const Polygons& TreeModelVolumes::getAvoidance(const coord_t orig_radius, LayerI
|
|||||||
|
|
||||||
const Polygons& TreeModelVolumes::getPlaceableAreas(const coord_t orig_radius, LayerIndex layer_idx, std::function<void()> throw_on_cancel) const
|
const Polygons& TreeModelVolumes::getPlaceableAreas(const coord_t orig_radius, LayerIndex layer_idx, std::function<void()> throw_on_cancel) const
|
||||||
{
|
{
|
||||||
if (orig_radius == 0)
|
|
||||||
return this->getCollision(0, layer_idx, true);
|
|
||||||
|
|
||||||
const coord_t radius = ceilRadius(orig_radius);
|
const coord_t radius = ceilRadius(orig_radius);
|
||||||
if (std::optional<std::reference_wrapper<const Polygons>> result = m_placeable_areas_cache.getArea({ radius, layer_idx }); result)
|
if (std::optional<std::reference_wrapper<const Polygons>> result = m_placeable_areas_cache.getArea({ radius, layer_idx }); result)
|
||||||
return (*result).get();
|
return (*result).get();
|
||||||
@ -426,6 +424,10 @@ const Polygons& TreeModelVolumes::getPlaceableAreas(const coord_t orig_radius, L
|
|||||||
BOOST_LOG_TRIVIAL(error_level_not_in_cache) << "Had to calculate Placeable Areas at radius " << radius << " and layer " << layer_idx << ", but precalculate was called. Performance may suffer!";
|
BOOST_LOG_TRIVIAL(error_level_not_in_cache) << "Had to calculate Placeable Areas at radius " << radius << " and layer " << layer_idx << ", but precalculate was called. Performance may suffer!";
|
||||||
tree_supports_show_error("Not precalculated Placeable areas requested."sv, false);
|
tree_supports_show_error("Not precalculated Placeable areas requested."sv, false);
|
||||||
}
|
}
|
||||||
|
if (orig_radius == 0)
|
||||||
|
// Placable areas for radius 0 are calculated in the general collision code.
|
||||||
|
return this->getCollision(0, layer_idx, true);
|
||||||
|
else
|
||||||
const_cast<TreeModelVolumes*>(this)->calculatePlaceables(radius, layer_idx, throw_on_cancel);
|
const_cast<TreeModelVolumes*>(this)->calculatePlaceables(radius, layer_idx, throw_on_cancel);
|
||||||
return getPlaceableAreas(orig_radius, layer_idx, throw_on_cancel);
|
return getPlaceableAreas(orig_radius, layer_idx, throw_on_cancel);
|
||||||
}
|
}
|
||||||
@ -470,6 +472,7 @@ void TreeModelVolumes::calculateCollision(const std::vector<RadiusLayerPair> &ke
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate collisions and placable areas for radius and for layer 0 to max_layer_idx inclusive.
|
||||||
void TreeModelVolumes::calculateCollision(const coord_t radius, const LayerIndex max_layer_idx, std::function<void()> throw_on_cancel)
|
void TreeModelVolumes::calculateCollision(const coord_t radius, const LayerIndex max_layer_idx, std::function<void()> throw_on_cancel)
|
||||||
{
|
{
|
||||||
// assert(radius == this->ceilRadius(radius));
|
// assert(radius == this->ceilRadius(radius));
|
||||||
@ -480,12 +483,14 @@ void TreeModelVolumes::calculateCollision(const coord_t radius, const LayerIndex
|
|||||||
std::sort(layer_outline_indices.begin(), layer_outline_indices.end(),
|
std::sort(layer_outline_indices.begin(), layer_outline_indices.end(),
|
||||||
[this](size_t i, size_t j) { return m_layer_outlines[i].second.size() < m_layer_outlines[j].second.size(); });
|
[this](size_t i, size_t j) { return m_layer_outlines[i].second.size() < m_layer_outlines[j].second.size(); });
|
||||||
|
|
||||||
const LayerIndex min_layer_last = m_collision_cache.getMaxCalculatedLayer(radius);
|
// Layer range for which the collisions will be calculated.
|
||||||
std::vector<Polygons> data(max_layer_idx + 1 - min_layer_last, Polygons{});
|
LayerPolygonCache data;
|
||||||
|
data.allocate(m_collision_cache.getMaxCalculatedLayer(radius) + 1, max_layer_idx + 1);
|
||||||
|
|
||||||
const bool calculate_placable = m_support_rests_on_model && radius == 0;
|
const bool calculate_placable = m_support_rests_on_model && radius == 0;
|
||||||
std::vector<Polygons> data_placeable;
|
LayerPolygonCache data_placeable;
|
||||||
if (calculate_placable)
|
if (calculate_placable)
|
||||||
data_placeable = std::vector<Polygons>(max_layer_idx + 1 - min_layer_last, Polygons{});
|
data_placeable.allocate(data.idx_begin, data.idx_end);
|
||||||
|
|
||||||
for (size_t outline_idx : layer_outline_indices)
|
for (size_t outline_idx : layer_outline_indices)
|
||||||
if (const std::vector<Polygons> &outlines = m_layer_outlines[outline_idx].second; ! outlines.empty()) {
|
if (const std::vector<Polygons> &outlines = m_layer_outlines[outline_idx].second; ! outlines.empty()) {
|
||||||
@ -493,8 +498,6 @@ void TreeModelVolumes::calculateCollision(const coord_t radius, const LayerIndex
|
|||||||
const coord_t layer_height = settings.layer_height;
|
const coord_t layer_height = settings.layer_height;
|
||||||
const int z_distance_bottom_layers = int(round(double(settings.support_bottom_distance) / double(layer_height)));
|
const int z_distance_bottom_layers = int(round(double(settings.support_bottom_distance) / double(layer_height)));
|
||||||
const int z_distance_top_layers = int(round(double(settings.support_top_distance) / double(layer_height)));
|
const int z_distance_top_layers = int(round(double(settings.support_top_distance) / double(layer_height)));
|
||||||
const LayerIndex max_required_layer = std::min<LayerIndex>(outlines.size(), max_layer_idx + std::max(coord_t(1), z_distance_top_layers));
|
|
||||||
const LayerIndex min_layer_bottom = std::max<LayerIndex>(0, min_layer_last - int(z_distance_bottom_layers));
|
|
||||||
const coord_t xy_distance = outline_idx == m_current_outline_idx ? m_current_min_xy_dist :
|
const coord_t xy_distance = outline_idx == m_current_outline_idx ? m_current_min_xy_dist :
|
||||||
// technically this causes collision for the normal xy_distance to be larger by m_current_min_xy_dist_delta for all
|
// technically this causes collision for the normal xy_distance to be larger by m_current_min_xy_dist_delta for all
|
||||||
// not currently processing meshes as this delta will be added at request time.
|
// not currently processing meshes as this delta will be added at request time.
|
||||||
@ -505,35 +508,40 @@ void TreeModelVolumes::calculateCollision(const coord_t radius, const LayerIndex
|
|||||||
settings.support_xy_distance;
|
settings.support_xy_distance;
|
||||||
|
|
||||||
// 1) Calculate offsets of collision areas in parallel.
|
// 1) Calculate offsets of collision areas in parallel.
|
||||||
std::vector<Polygons> collision_areas_offsetted(max_required_layer + 1 - min_layer_bottom);
|
LayerPolygonCache collision_areas_offsetted;
|
||||||
tbb::parallel_for(tbb::blocked_range<LayerIndex>(min_layer_bottom, max_required_layer + 1),
|
collision_areas_offsetted.allocate(
|
||||||
[&outlines, &machine_border = std::as_const(m_machine_border), offset_value = radius + xy_distance, min_layer_bottom, &collision_areas_offsetted, &throw_on_cancel]
|
std::max<LayerIndex>(0, data.idx_begin - z_distance_bottom_layers),
|
||||||
|
std::min<LayerIndex>(outlines.size(), data.idx_end + z_distance_top_layers));
|
||||||
|
tbb::parallel_for(tbb::blocked_range<LayerIndex>(collision_areas_offsetted.idx_begin, collision_areas_offsetted.idx_end),
|
||||||
|
[&outlines, &machine_border = std::as_const(m_machine_border), offset_value = radius + xy_distance, &collision_areas_offsetted, &throw_on_cancel]
|
||||||
(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 collision_areas = machine_border;
|
Polygons collision_areas = machine_border;
|
||||||
append(collision_areas, outlines[layer_idx]);
|
append(collision_areas, outlines[layer_idx]);
|
||||||
// jtRound is not needed here, as the overshoot can not cause errors in the algorithm, because no assumptions are made about the model.
|
// jtRound is not needed here, as the overshoot can not cause errors in the algorithm, because no assumptions are made about the model.
|
||||||
// if a key does not exist when it is accessed it is added!
|
// if a key does not exist when it is accessed it is added!
|
||||||
collision_areas_offsetted[layer_idx - min_layer_bottom] = offset_value == 0 ? union_(collision_areas) : offset(union_ex(collision_areas), offset_value, ClipperLib::jtMiter, 1.2);
|
collision_areas_offsetted[layer_idx] = offset_value == 0 ?
|
||||||
|
union_(collision_areas) :
|
||||||
|
offset(union_ex(collision_areas), offset_value, ClipperLib::jtMiter, 1.2);
|
||||||
throw_on_cancel();
|
throw_on_cancel();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 2) Sum over top / bottom ranges.
|
// 2) Sum over top / bottom ranges.
|
||||||
const bool last = outline_idx == layer_outline_indices.size();
|
const bool processing_last_mesh = 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>(data.idx_begin, data.idx_end),
|
||||||
[&collision_areas_offsetted, &outlines, &machine_border = m_machine_border, &anti_overhang = m_anti_overhang, min_layer_bottom, radius,
|
[&collision_areas_offsetted, &outlines, &machine_border = m_machine_border, &anti_overhang = m_anti_overhang, radius,
|
||||||
xy_distance, z_distance_bottom_layers, z_distance_top_layers, min_resolution = m_min_resolution, &data, min_layer_last, last, &throw_on_cancel]
|
xy_distance, z_distance_bottom_layers, z_distance_top_layers, min_resolution = m_min_resolution, &data, processing_last_mesh, &throw_on_cancel]
|
||||||
(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 <= 0; ++ i)
|
||||||
int j = layer_idx + i - min_layer_bottom;
|
if (int j = layer_idx + i; collision_areas_offsetted.has(j))
|
||||||
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) {
|
for (int i = 1; i <= z_distance_top_layers; ++ i)
|
||||||
|
if (int j = layer_idx + i; j < int(outlines.size())) {
|
||||||
Polygons collision_areas_original = machine_border;
|
Polygons collision_areas_original = machine_border;
|
||||||
append(collision_areas_original, outlines[layer_idx + i]);
|
append(collision_areas_original, outlines[j]);
|
||||||
|
|
||||||
// If just the collision (including the xy distance) of the layers above is accumulated, it leads to the
|
// If just the collision (including the xy distance) of the layers above is accumulated, it leads to the
|
||||||
// following issue:
|
// following issue:
|
||||||
@ -566,37 +574,37 @@ void TreeModelVolumes::calculateCollision(const coord_t radius, const LayerIndex
|
|||||||
// the conditional -0.5 ensures that plastic can never touch on the diagonal
|
// 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
|
// 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.
|
// not support an overhang<90 degree than to risk fusing to it.
|
||||||
|
append(collisions, offset(union_ex(collision_areas_original), radius + required_range_x, ClipperLib::jtMiter, 1.2));
|
||||||
collision_areas_original = offset(union_ex(collision_areas_original), radius + required_range_x, ClipperLib::jtMiter, 1.2);
|
|
||||||
append(collisions, collision_areas_original);
|
|
||||||
}
|
}
|
||||||
}
|
collisions = processing_last_mesh && layer_idx < int(anti_overhang.size()) ?
|
||||||
collisions = last && layer_idx < int(anti_overhang.size()) ? union_(collisions, offset(union_ex(anti_overhang[layer_idx]), radius, ClipperLib::jtMiter, 1.2)) : union_(collisions);
|
union_(collisions, offset(union_ex(anti_overhang[layer_idx]), radius, ClipperLib::jtMiter, 1.2)) :
|
||||||
auto &dst = data[layer_idx - (min_layer_last + 1)];
|
union_(collisions);
|
||||||
if (last) {
|
auto &dst = data[layer_idx];
|
||||||
|
if (processing_last_mesh) {
|
||||||
if (! dst.empty())
|
if (! dst.empty())
|
||||||
collisions = union_(collisions, dst);
|
collisions = union_(collisions, dst);
|
||||||
dst = polygons_simplify(collisions, min_resolution);
|
dst = polygons_simplify(collisions, min_resolution);
|
||||||
} else
|
} else
|
||||||
append(dst, collisions);
|
append(dst, std::move(collisions));
|
||||||
throw_on_cancel();
|
throw_on_cancel();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 3) Optionally calculate placables.
|
// 3) Optionally calculate placables.
|
||||||
if (calculate_placable) {
|
if (calculate_placable) {
|
||||||
// Calculating both the collision areas and placable areas.
|
// Now calculate the placable areas.
|
||||||
tbb::parallel_for(tbb::blocked_range<LayerIndex>(std::max(min_layer_last + 1, z_distance_bottom_layers + 1), max_layer_idx + 1),
|
tbb::parallel_for(tbb::blocked_range<LayerIndex>(std::max(data.idx_begin, 1), data.idx_end),
|
||||||
[&collision_areas_offsetted, &anti_overhang = m_anti_overhang, min_layer_bottom, z_distance_bottom_layers, last, min_resolution = m_min_resolution, &data_placeable, min_layer_last, &throw_on_cancel]
|
[&collision_areas_offsetted, &anti_overhang = m_anti_overhang, processing_last_mesh,
|
||||||
|
min_resolution = m_min_resolution, &data_placeable, &throw_on_cancel]
|
||||||
(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) {
|
||||||
LayerIndex layer_idx_below = layer_idx - (z_distance_bottom_layers + 1) - min_layer_bottom;
|
LayerIndex layer_idx_below = layer_idx - 1;
|
||||||
assert(layer_idx_below >= 0);
|
assert(layer_idx_below >= 0);
|
||||||
auto ¤t = collision_areas_offsetted[layer_idx - min_layer_bottom];
|
const Polygons ¤t = collision_areas_offsetted[layer_idx];
|
||||||
auto &below = collision_areas_offsetted[layer_idx_below];
|
const Polygons &below = collision_areas_offsetted[layer_idx_below];
|
||||||
auto placable = diff(below, layer_idx < int(anti_overhang.size()) ? union_(current, anti_overhang[layer_idx - (z_distance_bottom_layers + 1)]) : current);
|
Polygons placable = diff(below, layer_idx_below < int(anti_overhang.size()) ? union_(current, anti_overhang[layer_idx_below]) : current);
|
||||||
auto &dst = data_placeable[layer_idx - (min_layer_last + 1)];
|
auto &dst = data_placeable[layer_idx];
|
||||||
if (last) {
|
if (processing_last_mesh) {
|
||||||
if (! dst.empty())
|
if (! dst.empty())
|
||||||
placable = union_(placable, dst);
|
placable = union_(placable, dst);
|
||||||
dst = polygons_simplify(placable, min_resolution);
|
dst = polygons_simplify(placable, min_resolution);
|
||||||
@ -619,9 +627,9 @@ void TreeModelVolumes::calculateCollision(const coord_t radius, const LayerIndex
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
throw_on_cancel();
|
throw_on_cancel();
|
||||||
m_collision_cache.insert(std::move(data), min_layer_last + 1, radius);
|
m_collision_cache.insert(std::move(data), radius);
|
||||||
if (calculate_placable)
|
if (calculate_placable)
|
||||||
m_placeable_areas_cache.insert(std::move(data_placeable), min_layer_last + 1, radius);
|
m_placeable_areas_cache.insert(std::move(data_placeable), radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TreeModelVolumes::calculateCollisionHolefree(const std::vector<RadiusLayerPair> &keys, std::function<void()> throw_on_cancel)
|
void TreeModelVolumes::calculateCollisionHolefree(const std::vector<RadiusLayerPair> &keys, std::function<void()> throw_on_cancel)
|
||||||
|
@ -328,6 +328,26 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Caching polygons for a range of layers.
|
||||||
|
struct LayerPolygonCache {
|
||||||
|
std::vector<Polygons> polygons;
|
||||||
|
LayerIndex idx_begin;
|
||||||
|
LayerIndex idx_end;
|
||||||
|
|
||||||
|
void allocate(LayerIndex aidx_begin, LayerIndex aidx_end) {
|
||||||
|
this->idx_begin = aidx_begin;
|
||||||
|
this->idx_end = aidx_end;
|
||||||
|
this->polygons.assign(aidx_end - aidx_begin, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
LayerIndex begin() const { return idx_begin; }
|
||||||
|
LayerIndex end() const { return idx_end; }
|
||||||
|
size_t size() const { return polygons.size(); }
|
||||||
|
|
||||||
|
bool has(LayerIndex idx) const { return idx >= idx_begin && idx < idx_end; }
|
||||||
|
Polygons& operator[](LayerIndex idx) { return polygons[idx + idx_begin]; }
|
||||||
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Convenience typedef for the keys to the caches
|
* \brief Convenience typedef for the keys to the caches
|
||||||
*/
|
*/
|
||||||
@ -363,6 +383,13 @@ private:
|
|||||||
for (auto &d : in)
|
for (auto &d : in)
|
||||||
m_data[first_layer_idx ++].emplace(radius, std::move(d));
|
m_data[first_layer_idx ++].emplace(radius, std::move(d));
|
||||||
}
|
}
|
||||||
|
void insert(LayerPolygonCache &&in, coord_t radius) {
|
||||||
|
std::lock_guard<std::mutex> guard(m_mutex);
|
||||||
|
LayerIndex i = in.idx_begin;
|
||||||
|
allocate_layers(i + LayerIndex(in.size()));
|
||||||
|
for (auto &d : in.polygons)
|
||||||
|
m_data[i ++].emplace(radius, std::move(d));
|
||||||
|
}
|
||||||
/*!
|
/*!
|
||||||
* \brief Checks a cache for a given RadiusLayerPair and returns it if it is found
|
* \brief Checks a cache for a given RadiusLayerPair and returns it if it is found
|
||||||
* \param key RadiusLayerPair of the requested areas. The radius will be calculated up to the provided layer.
|
* \param key RadiusLayerPair of the requested areas. The radius will be calculated up to the provided layer.
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -122,7 +122,7 @@ struct SupportElementStateBits {
|
|||||||
bool use_min_xy_dist : 1;
|
bool use_min_xy_dist : 1;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief True if this Element or any parent provides support to a support roof.
|
* \brief True if this Element or any parent (element above) provides support to a support roof.
|
||||||
*/
|
*/
|
||||||
bool supports_roof : 1;
|
bool supports_roof : 1;
|
||||||
|
|
||||||
@ -193,7 +193,7 @@ struct SupportElementState : public SupportElementStateBits
|
|||||||
double elephant_foot_increases;
|
double elephant_foot_increases;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief The element trys not to move until this dtt is reached, is set to 0 if the element had to move.
|
* \brief The element tries to not move until this dtt is reached, is set to 0 if the element had to move.
|
||||||
*/
|
*/
|
||||||
uint32_t dont_move_until;
|
uint32_t dont_move_until;
|
||||||
|
|
||||||
@ -218,6 +218,8 @@ struct SupportElementState : public SupportElementStateBits
|
|||||||
dst.skip_ovalisation = false;
|
dst.skip_ovalisation = false;
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool locked() const { return this->distance_to_top < this->dont_move_until; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SupportElement
|
struct SupportElement
|
||||||
|
@ -291,7 +291,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
|
|||||||
(config->opt_bool("support_material") ||
|
(config->opt_bool("support_material") ||
|
||||||
config->opt_int("support_material_enforce_layers") > 0);
|
config->opt_int("support_material_enforce_layers") > 0);
|
||||||
for (const std::string& key : { "support_tree_angle", "support_tree_angle_slow", "support_tree_branch_diameter",
|
for (const std::string& key : { "support_tree_angle", "support_tree_angle_slow", "support_tree_branch_diameter",
|
||||||
"support_tree_branch_diameter_angle", "support_tree_tip_diameter", "support_tree_top_rate" })
|
"support_tree_branch_diameter_angle", "support_tree_tip_diameter", "support_tree_branch_distance", "support_tree_top_rate" })
|
||||||
toggle_field(key, has_organic_supports);
|
toggle_field(key, has_organic_supports);
|
||||||
|
|
||||||
for (auto el : { "support_material_bottom_interface_layers", "support_material_interface_spacing", "support_material_interface_extruder",
|
for (auto el : { "support_material_bottom_interface_layers", "support_material_interface_spacing", "support_material_interface_extruder",
|
||||||
|
@ -1531,6 +1531,7 @@ void TabPrint::build()
|
|||||||
optgroup->append_single_option_line("support_tree_branch_diameter", category_path + "tree_branch_diameter");
|
optgroup->append_single_option_line("support_tree_branch_diameter", category_path + "tree_branch_diameter");
|
||||||
optgroup->append_single_option_line("support_tree_branch_diameter_angle", category_path + "tree_branch_diameter_angle");
|
optgroup->append_single_option_line("support_tree_branch_diameter_angle", category_path + "tree_branch_diameter_angle");
|
||||||
optgroup->append_single_option_line("support_tree_tip_diameter", category_path + "tree_tip_diameter");
|
optgroup->append_single_option_line("support_tree_tip_diameter", category_path + "tree_tip_diameter");
|
||||||
|
optgroup->append_single_option_line("support_tree_branch_distance", category_path + "tree_branch_distance");
|
||||||
optgroup->append_single_option_line("support_tree_top_rate", category_path + "tree_top_rate");
|
optgroup->append_single_option_line("support_tree_top_rate", category_path + "tree_top_rate");
|
||||||
|
|
||||||
page = add_options_page(L("Speed"), "time");
|
page = add_options_page(L("Speed"), "time");
|
||||||
|
Loading…
Reference in New Issue
Block a user