Merge remote-tracking branch 'remotes/origin/master' into vb_ensurovani

This commit is contained in:
Vojtech Bubnik 2023-02-17 15:20:47 +01:00
commit 978f5c8b47
163 changed files with 38820 additions and 34634 deletions

View file

@ -154,7 +154,7 @@ static std::vector<std::pair<TreeSupportSettings, std::vector<size_t>>> group_me
const PrintObjectConfig &object_config = print_object.config();
#endif // NDEBUG
// Support must be enabled and set to Tree style.
assert(object_config.support_material);
assert(object_config.support_material || object_config.support_material_enforce_layers > 0);
assert(object_config.support_material_style == smsTree || object_config.support_material_style == smsOrganic);
bool found_existing_group = false;
@ -226,8 +226,9 @@ void tree_supports_show_error(std::string_view message, bool critical)
{
std::vector<Polygons> out(print_object.layer_count(), Polygons{});
const PrintConfig &print_config = print_object.print()->config();
const PrintObjectConfig &config = print_object.config();
const bool support_auto = config.support_material_auto.value;
const bool support_auto = config.support_material.value && config.support_material_auto.value;
const int support_enforce_layers = config.support_material_enforce_layers.value;
std::vector<Polygons> enforcers_layers{ print_object.slice_support_enforcers() };
std::vector<Polygons> blockers_layers{ print_object.slice_support_blockers() };
@ -240,8 +241,10 @@ void tree_supports_show_error(std::string_view message, bool critical)
//FIXME this is a fudge constant!
auto enforcer_overhang_offset = scaled<double>(config.support_tree_tip_diameter.value);
tbb::parallel_for(tbb::blocked_range<LayerIndex>(1, out.size()),
[&print_object, &enforcers_layers, &blockers_layers, support_auto, support_enforce_layers, support_threshold_auto, tan_threshold, enforcer_overhang_offset, &throw_on_cancel, &out]
size_t num_overhang_layers = support_auto ? out.size() : std::max(size_t(support_enforce_layers), enforcers_layers.size());
tbb::parallel_for(tbb::blocked_range<LayerIndex>(1, num_overhang_layers),
[&print_object, &config, &print_config, &enforcers_layers, &blockers_layers,
support_auto, support_enforce_layers, support_threshold_auto, tan_threshold, enforcer_overhang_offset, &throw_on_cancel, &out]
(const tbb::blocked_range<LayerIndex> &range) {
for (LayerIndex layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
const Layer &current_layer = *print_object.get_layer(layer_id);
@ -274,6 +277,11 @@ void tree_supports_show_error(std::string_view message, bool critical)
}
if (! (enforced_layer || blockers_layers.empty() || blockers_layers[layer_id].empty()))
overhangs = diff(overhangs, blockers_layers[layer_id], ApplySafetyOffset::Yes);
if (config.dont_support_bridges) {
for (const LayerRegion *layerm : current_layer.regions())
remove_bridges_from_contacts(print_config, lower_layer, *layerm,
float(layerm->flow(frExternalPerimeter).scaled_width()), overhangs);
}
}
//check_self_intersections(overhangs, "generate_overhangs1");
if (! enforcers_layers.empty() && ! enforcers_layers[layer_id].empty()) {
@ -488,15 +496,15 @@ static std::optional<std::pair<Point, size_t>> polyline_sample_next_point_at_dis
Vec2d xf = p0f - foot_pt;
// Squared distance of "start_pt" from the ray (p0, p1).
double l2_from_line = xf.squaredNorm();
double det = dist2 - l2_from_line;
if (det > - SCALED_EPSILON) {
// Squared distance of an intersection point of a circle with center at the foot point.
if (double l2_intersection = dist2 - l2_from_line;
l2_intersection > - SCALED_EPSILON) {
// The ray (p0, p1) touches or intersects a circle centered at "start_pt" with radius "dist".
// Distance of the circle intersection point from the foot point.
double dist_circle_intersection = std::sqrt(std::max(0., det));
if ((v - foot_pt).cast<double>().norm() > dist_circle_intersection) {
l2_intersection = std::max(l2_intersection, 0.);
if ((v - foot_pt).cast<double>().squaredNorm() >= l2_intersection) {
// Intersection of the circle with the segment (p0, p1) is on the right side (close to p1) from the foot point.
Point p = p0 + (foot_pt + v * (dist_circle_intersection / sqrt(l2v))).cast<coord_t>();
Point p = p0 + (foot_pt + v * sqrt(l2_intersection / l2v)).cast<coord_t>();
validate_range(p);
return std::pair<Point, size_t>{ p, i - 1 };
}
@ -908,7 +916,7 @@ static void generate_initial_areas(
//FIXME Vojtech: This is not sufficient for support enforcers to work.
//FIXME There is no account for the support overhang angle.
//FIXME There is no account for the width of the collision regions.
const coord_t extra_outset = std::max(coord_t(0), mesh_config.min_radius - mesh_config.support_line_width) + (min_xy_dist ? mesh_config.support_line_width / 2 : 0)
const coord_t extra_outset = std::max(coord_t(0), mesh_config.min_radius - mesh_config.support_line_width / 2) + (min_xy_dist ? mesh_config.support_line_width / 2 : 0)
//FIXME this is a heuristic value for support enforcers to work.
// + 10 * mesh_config.support_line_width;
;
@ -923,7 +931,9 @@ static void generate_initial_areas(
// does not turn valid in double the amount of layers a slope of support angle would take to travel xy_distance, nothing reasonable will come from it.
// The 2*z_distance_delta is only a catch for when the support angle is very high.
// Used only if not min_xy_dist.
const coord_t max_overhang_insert_lag = std::max<coord_t>(round_up_divide(mesh_config.xy_distance, max_overhang_speed / 2), 2 * mesh_config.z_distance_top_layers);
const coord_t max_overhang_insert_lag = mesh_config.z_distance_top_layers > 0 ?
std::max<coord_t>(round_up_divide(mesh_config.xy_distance, max_overhang_speed / 2), 2 * mesh_config.z_distance_top_layers) :
0;
//FIXME
size_t num_support_layers = print_object.layer_count();
@ -1069,9 +1079,8 @@ static void generate_initial_areas(
Polygons overhang_regular;
{
const Polygons &overhang_raw = overhangs[layer_idx + z_distance_delta];
overhang_regular = mesh_group_settings.support_offset == 0 ?
overhang_raw :
safe_offset_inc(overhang_raw, mesh_group_settings.support_offset, relevant_forbidden, mesh_config.min_radius * 1.75 + mesh_config.xy_min_distance, 0, 1);
// When support_offset = 0 safe_offset_inc will only be the difference between overhang_raw and relevant_forbidden, that has to be calculated anyway.
overhang_regular = safe_offset_inc(overhang_raw, mesh_group_settings.support_offset, relevant_forbidden, mesh_config.min_radius * 1.75 + mesh_config.xy_min_distance, 0, 1);
//check_self_intersections(overhang_regular, "overhang_regular1");
// offset ensures that areas that could be supported by a part of a support line, are not considered unsupported overhang
@ -2497,8 +2506,10 @@ static void create_nodes_from_area(
// Point is chosen based on an inaccurate estimate where the branches will split into two, but every point inside the influence area would produce a valid result.
{
SupportElements *layer_above = move_bounds.size() > 1 ? &move_bounds[1] : nullptr;
for (SupportElement &elem : *layer_above)
elem.state.marked = false;
if (layer_above) {
for (SupportElement &elem : *layer_above)
elem.state.marked = false;
}
for (SupportElement &init : move_bounds.front()) {
init.state.result_on_layer = move_inside_if_outside(init.influence_area, init.state.next_position);
// Also set the parent nodes, as these will be required for the first iteration of the loop below and mark the parent nodes.
@ -2931,7 +2942,11 @@ static void finalize_interface_and_support_areas(
std::function<void()> throw_on_cancel)
{
InterfacePreference interface_pref = config.interface_preference; // InterfacePreference::SupportLinesOverwriteInterface;
assert(std::all_of(bottom_contacts.begin(), bottom_contacts.end(), [](auto *p) { return p == nullptr; }));
// assert(std::all_of(top_contacts.begin(), top_contacts.end(), [](auto* p) { return p == nullptr; }));
assert(std::all_of(intermediate_layers.begin(), intermediate_layers.end(), [](auto* p) { return p == nullptr; }));
InterfacePreference interface_pref = config.interface_preference; // InterfacePreference::InterfaceAreaOverwritesSupport;
#ifdef SLIC3R_TREESUPPORTS_PROGRESS
double progress_total = TREE_PROGRESS_PRECALC_AVO + TREE_PROGRESS_PRECALC_COLL + TREE_PROGRESS_GENERATE_NODES + TREE_PROGRESS_AREA_CALC + TREE_PROGRESS_GENERATE_BRANCH_AREAS + TREE_PROGRESS_SMOOTH_BRANCH_AREAS;
@ -2942,29 +2957,41 @@ static void finalize_interface_and_support_areas(
tbb::parallel_for(tbb::blocked_range<size_t>(0, support_layer_storage.size()),
[&](const tbb::blocked_range<size_t> &range) {
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
// Most of the time in this function is this union call. Can take 300+ ms when a lot of areas are to be unioned.
support_layer_storage[layer_idx] = smooth_outward(union_(support_layer_storage[layer_idx]), config.support_line_width); //FIXME was .smooth(50);
//smooth_outward(closing(std::move(bottom), closing_distance + minimum_island_radius, closing_distance, SUPPORT_SURFACES_OFFSET_PARAMETERS), smoothing_distance) :
// simplify a bit, to ensure the output does not contain outrageous amounts of vertices. Should not be necessary, just a precaution.
support_layer_storage[layer_idx] = polygons_simplify(support_layer_storage[layer_idx], std::min(scaled<double>(0.03), double(config.resolution)));
// Subtract support lines of the branches from the roof
SupportGeneratorLayer*& support_roof = top_contacts[layer_idx];
if (! support_roof_storage[layer_idx].empty() || support_roof != nullptr) {
if (support_roof == nullptr) {
support_roof = &layer_allocate(layer_storage, layer_storage_mutex, SupporLayerType::TopContact, print_object.slicing_parameters(), layer_idx);
support_roof->polygons = union_(support_roof_storage[layer_idx]);
} else
support_roof->polygons = union_(support_roof->polygons, support_roof_storage[layer_idx]);
SupportGeneratorLayer *support_roof = top_contacts[layer_idx];
Polygons support_roof_polygons;
if (! support_roof->polygons.empty() &&
area(intersection(support_layer_storage[layer_idx], support_roof->polygons)) > tiny_area_threshold) {
if (Polygons &src = support_roof_storage[layer_idx]; ! src.empty()) {
if (support_roof != nullptr && ! support_roof->polygons.empty()) {
support_roof_polygons = union_(src, support_roof->polygons);
support_roof->polygons.clear();
} else
support_roof_polygons = std::move(src);
} else if (support_roof != nullptr) {
support_roof_polygons = std::move(support_roof->polygons);
support_roof->polygons.clear();
}
assert(intermediate_layers[layer_idx] == nullptr);
Polygons base_layer_polygons = std::move(support_layer_storage[layer_idx]);
if (! base_layer_polygons.empty()) {
// Most of the time in this function is this union call. Can take 300+ ms when a lot of areas are to be unioned.
base_layer_polygons = smooth_outward(union_(base_layer_polygons), config.support_line_width); //FIXME was .smooth(50);
//smooth_outward(closing(std::move(bottom), closing_distance + minimum_island_radius, closing_distance, SUPPORT_SURFACES_OFFSET_PARAMETERS), smoothing_distance) :
// simplify a bit, to ensure the output does not contain outrageous amounts of vertices. Should not be necessary, just a precaution.
base_layer_polygons = polygons_simplify(base_layer_polygons, std::min(scaled<double>(0.03), double(config.resolution)));
}
if (! support_roof_polygons.empty() && ! base_layer_polygons.empty()) {
// if (area(intersection(base_layer_polygons, support_roof_polygons)) > tiny_area_threshold)
{
switch (interface_pref) {
case InterfacePreference::InterfaceAreaOverwritesSupport:
support_layer_storage[layer_idx] = diff(support_layer_storage[layer_idx], support_roof->polygons);
base_layer_polygons = diff(base_layer_polygons, support_roof_polygons);
break;
case InterfacePreference::SupportAreaOverwritesInterface:
support_roof->polygons = diff(support_roof->polygons, support_layer_storage[layer_idx]);
support_roof_polygons = diff(support_roof_polygons, base_layer_polygons);
break;
//FIXME
#if 1
@ -2979,14 +3006,14 @@ static void finalize_interface_and_support_areas(
Polygons interface_lines = offset(to_polylines(
generate_support_infill_lines(support_roof->polygons, true, layer_idx, config.support_roof_line_distance)),
config.support_roof_line_width / 2);
support_layer_storage[layer_idx] = diff(support_layer_storage[layer_idx], interface_lines);
base_layer_polygons = diff(base_layer_polygons, interface_lines);
break;
}
case InterfacePreference::SupportLinesOverwriteInterface:
{
// Hatch the support roof interfaces, offset them by their line width and subtract them from support base.
Polygons tree_lines = union_(offset(to_polylines(
generate_support_infill_lines(support_layer_storage[layer_idx], false, layer_idx, config.support_line_distance, true)),
generate_support_infill_lines(base_layer_polygons, false, layer_idx, config.support_line_distance, true)),
config.support_line_width / 2));
// do not draw roof where the tree is. I prefer it this way as otherwise the roof may cut of a branch from its support below.
support_roof->polygons = diff(support_roof->polygons, tree_lines);
@ -3000,10 +3027,10 @@ static void finalize_interface_and_support_areas(
}
// Subtract support floors from the support area and add them to the support floor instead.
if (config.support_bottom_layers > 0 && !support_layer_storage[layer_idx].empty()) {
if (config.support_bottom_layers > 0 && ! base_layer_polygons.empty()) {
SupportGeneratorLayer*& support_bottom = bottom_contacts[layer_idx];
Polygons layer_outset = diff_clipped(
config.support_bottom_offset > 0 ? offset(support_layer_storage[layer_idx], config.support_bottom_offset, jtMiter, 1.2) : support_layer_storage[layer_idx],
config.support_bottom_offset > 0 ? offset(base_layer_polygons, config.support_bottom_offset, jtMiter, 1.2) : base_layer_polygons,
volumes.getCollision(0, layer_idx, false));
Polygons floor_layer;
size_t layers_below = 0;
@ -3021,15 +3048,18 @@ static void finalize_interface_and_support_areas(
if (support_bottom == nullptr)
support_bottom = &layer_allocate(layer_storage, layer_storage_mutex, SupporLayerType::BottomContact, print_object.slicing_parameters(), layer_idx);
support_bottom->polygons = union_(floor_layer, support_bottom->polygons);
support_layer_storage[layer_idx] = diff_clipped(support_layer_storage[layer_idx], offset(support_bottom->polygons, scaled<float>(0.01), jtMiter, 1.2)); // Subtract the support floor from the normal support.
base_layer_polygons = diff_clipped(base_layer_polygons, offset(support_bottom->polygons, scaled<float>(0.01), jtMiter, 1.2)); // Subtract the support floor from the normal support.
}
}
if (! support_layer_storage[layer_idx].empty()) {
SupportGeneratorLayer *&l = intermediate_layers[layer_idx];
if (l == nullptr)
l = &layer_allocate(layer_storage, layer_storage_mutex, SupporLayerType::Base, print_object.slicing_parameters(), layer_idx);
append(l->polygons, union_(support_layer_storage[layer_idx]));
if (! support_roof_polygons.empty()) {
if (support_roof == nullptr)
support_roof = top_contacts[layer_idx] = &layer_allocate(layer_storage, layer_storage_mutex, SupporLayerType::TopContact, print_object.slicing_parameters(), layer_idx);
support_roof->polygons = union_(support_roof_polygons);
}
if (! base_layer_polygons.empty()) {
SupportGeneratorLayer *base_layer = intermediate_layers[layer_idx] = &layer_allocate(layer_storage, layer_storage_mutex, SupporLayerType::Base, print_object.slicing_parameters(), layer_idx);
base_layer->polygons = union_(base_layer_polygons);
}
#ifdef SLIC3R_TREESUPPORTS_PROGRESS
@ -3913,25 +3943,15 @@ static void slice_branches(
params.closing_radius = float(print_object.config().slice_closing_radius.value);
params.mode = MeshSlicingParams::SlicingMode::Positive;
std::vector<ExPolygons> slices = slice_mesh_ex(cummulative_mesh, slice_z, params, throw_on_cancel);
for (size_t layer_idx = 0; layer_idx < slice_z.size(); ++ layer_idx)
if (! slices[layer_idx].empty()) {
SupportGeneratorLayer *&l = intermediate_layers[layer_idx];
if (l == nullptr)
l = &layer_allocate(layer_storage, SupporLayerType::Base, slicing_params, layer_idx);
append(l->polygons, to_polygons(std::move(slices[layer_idx])));
}
// Trim the slices.
tbb::parallel_for(tbb::blocked_range<size_t>(0, intermediate_layers.size()),
std::vector<Polygons> support_layer_storage(move_bounds.size());
tbb::parallel_for(tbb::blocked_range<size_t>(0, slices.size()),
[&](const tbb::blocked_range<size_t> &range) {
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx)
if (SupportGeneratorLayer *layer = intermediate_layers[layer_idx]; layer) {
Polygons &poly = intermediate_layers[layer_idx]->polygons;
poly = diff_clipped(poly, volumes.getCollision(0, layer_idx, true));
}
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx)
if (ExPolygons &src = slices[layer_idx]; ! src.empty())
support_layer_storage[layer_idx] = diff_clipped(to_polygons(std::move(src)), volumes.getCollision(0, layer_idx, true));
});
std::vector<Polygons> support_layer_storage(move_bounds.size());
std::vector<Polygons> support_roof_storage(move_bounds.size());
finalize_interface_and_support_areas(print_object, volumes, config, overhangs, support_layer_storage, support_roof_storage,
bottom_contacts, top_contacts, intermediate_layers, layer_storage, throw_on_cancel);