One more fix for Organic supports & Raft :
Raft was not generated at all with Organic supports enabled, but no trees produced.
This commit is contained in:
parent
94d463b645
commit
2959de40ae
2 changed files with 152 additions and 129 deletions
|
@ -2954,7 +2954,7 @@ SupportGeneratorLayersPtr generate_raft_base(
|
||||||
Polygons columns;
|
Polygons columns;
|
||||||
Polygons first_layer;
|
Polygons first_layer;
|
||||||
if (columns_base != nullptr) {
|
if (columns_base != nullptr) {
|
||||||
if (columns_base->print_z > slicing_params.raft_contact_top_z - EPSILON) {
|
if (columns_base->bottom_print_z() > slicing_params.raft_interface_top_z - EPSILON) {
|
||||||
// Classic supports with colums above the raft interface.
|
// Classic supports with colums above the raft interface.
|
||||||
base = columns_base->polygons;
|
base = columns_base->polygons;
|
||||||
columns = base;
|
columns = base;
|
||||||
|
|
|
@ -993,6 +993,30 @@ inline SupportGeneratorLayer& layer_allocate(
|
||||||
return layer_initialize(layer_storage.back(), layer_type, slicing_params, config, layer_idx);
|
return layer_initialize(layer_storage.back(), layer_type, slicing_params, config, layer_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int generate_raft_contact(
|
||||||
|
const PrintObject &print_object,
|
||||||
|
const TreeSupportSettings &config,
|
||||||
|
SupportGeneratorLayersPtr &top_contacts,
|
||||||
|
SupportGeneratorLayerStorage &layer_storage)
|
||||||
|
{
|
||||||
|
int raft_contact_layer_idx = -1;
|
||||||
|
if (print_object.has_raft() && print_object.layer_count() > 0) {
|
||||||
|
// Produce raft contact layer outside of the tree support loop, so that no trees will be generated for the raft contact layer.
|
||||||
|
// Raft layers supporting raft contact interface will be produced by the classic raft generator.
|
||||||
|
// Find the raft contact layer.
|
||||||
|
raft_contact_layer_idx = int(config.raft_layers.size()) - 1;
|
||||||
|
while (raft_contact_layer_idx > 0 && config.raft_layers[raft_contact_layer_idx] > print_object.slicing_parameters().raft_contact_top_z + EPSILON)
|
||||||
|
-- raft_contact_layer_idx;
|
||||||
|
// Create the raft contact layer.
|
||||||
|
SupportGeneratorLayer &raft_contact_layer = layer_allocate(layer_storage, SupporLayerType::TopContact, print_object.slicing_parameters(), config, raft_contact_layer_idx);
|
||||||
|
top_contacts[raft_contact_layer_idx] = &raft_contact_layer;
|
||||||
|
const ExPolygons &lslices = print_object.get_layer(0)->lslices;
|
||||||
|
double expansion = print_object.config().raft_expansion.value;
|
||||||
|
raft_contact_layer.polygons = expansion > 0 ? expand(lslices, scaled<float>(expansion)) : to_polygons(lslices);
|
||||||
|
}
|
||||||
|
return raft_contact_layer_idx;
|
||||||
|
}
|
||||||
|
|
||||||
using SupportElements = std::deque<SupportElement>;
|
using SupportElements = std::deque<SupportElement>;
|
||||||
/*!
|
/*!
|
||||||
* \brief Creates the initial influence areas (that can later be propagated down) by placing them below the overhang.
|
* \brief Creates the initial influence areas (that can later be propagated down) by placing them below the overhang.
|
||||||
|
@ -1066,24 +1090,7 @@ static void generate_initial_areas(
|
||||||
const size_t num_raft_layers = config.raft_layers.size();
|
const size_t num_raft_layers = config.raft_layers.size();
|
||||||
const size_t num_support_layers = size_t(std::max(0, int(print_object.layer_count()) + int(num_raft_layers) - int(z_distance_delta)));
|
const size_t num_support_layers = size_t(std::max(0, int(print_object.layer_count()) + int(num_raft_layers) - int(z_distance_delta)));
|
||||||
const size_t first_support_layer = std::max(int(num_raft_layers) - int(z_distance_delta), 1);
|
const size_t first_support_layer = std::max(int(num_raft_layers) - int(z_distance_delta), 1);
|
||||||
size_t first_tree_layer = 0;
|
const int raft_contact_layer_idx = generate_raft_contact(print_object, config, top_contacts, layer_storage);
|
||||||
|
|
||||||
size_t raft_contact_layer_idx = std::numeric_limits<size_t>::max();
|
|
||||||
if (num_raft_layers > 0 && print_object.layer_count() > 0) {
|
|
||||||
// Produce raft contact layer outside of the tree support loop, so that no trees will be generated for the raft contact layer.
|
|
||||||
// Raft layers supporting raft contact interface will be produced by the classic raft generator.
|
|
||||||
// Find the raft contact layer.
|
|
||||||
raft_contact_layer_idx = config.raft_layers.size() - 1;
|
|
||||||
while (raft_contact_layer_idx > 0 && config.raft_layers[raft_contact_layer_idx] > print_object.slicing_parameters().raft_contact_top_z + EPSILON)
|
|
||||||
-- raft_contact_layer_idx;
|
|
||||||
// Create the raft contact layer.
|
|
||||||
SupportGeneratorLayer &raft_contact_layer = layer_allocate(layer_storage, SupporLayerType::TopContact, print_object.slicing_parameters(), config, raft_contact_layer_idx);
|
|
||||||
top_contacts[raft_contact_layer_idx] = &raft_contact_layer;
|
|
||||||
const ExPolygons &lslices = print_object.get_layer(0)->lslices;
|
|
||||||
double expansion = print_object.config().raft_expansion.value;
|
|
||||||
raft_contact_layer.polygons = expansion > 0 ? expand(lslices, scaled<float>(expansion)) : to_polygons(lslices);
|
|
||||||
first_tree_layer = print_object.slicing_parameters().raft_layers() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::mutex mutex_layer_storage, mutex_movebounds;
|
std::mutex mutex_layer_storage, mutex_movebounds;
|
||||||
std::vector<std::unordered_set<Point, PointHash>> already_inserted(num_support_layers);
|
std::vector<std::unordered_set<Point, PointHash>> already_inserted(num_support_layers);
|
||||||
|
@ -1436,47 +1443,50 @@ static void generate_initial_areas(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Remove tree tips that start below the raft contact,
|
if (raft_contact_layer_idx >= 0) {
|
||||||
// remove interface layers below the raft contact.
|
const size_t first_tree_layer = print_object.slicing_parameters().raft_layers() - 1;
|
||||||
for (size_t i = 0; i < first_tree_layer; ++i) {
|
// Remove tree tips that start below the raft contact,
|
||||||
top_contacts[i] = nullptr;
|
// remove interface layers below the raft contact.
|
||||||
move_bounds[i].clear();
|
for (size_t i = 0; i < first_tree_layer; ++i) {
|
||||||
}
|
top_contacts[i] = nullptr;
|
||||||
if (raft_contact_layer_idx != std::numeric_limits<size_t>::max() && print_object.config().raft_expansion.value > 0) {
|
move_bounds[i].clear();
|
||||||
// If any tips at first_tree_layer now are completely inside the expanded raft layer, remove them as well before they are propagated to the ground.
|
}
|
||||||
Polygons &raft_polygons = top_contacts[raft_contact_layer_idx]->polygons;
|
if (raft_contact_layer_idx >= 0 && print_object.config().raft_expansion.value > 0) {
|
||||||
EdgeGrid::Grid grid(get_extents(raft_polygons).inflated(SCALED_EPSILON));
|
// If any tips at first_tree_layer now are completely inside the expanded raft layer, remove them as well before they are propagated to the ground.
|
||||||
grid.create(raft_polygons, Polylines{}, coord_t(scale_(10.)));
|
Polygons &raft_polygons = top_contacts[raft_contact_layer_idx]->polygons;
|
||||||
SupportElements &first_layer_move_bounds = move_bounds[first_tree_layer];
|
EdgeGrid::Grid grid(get_extents(raft_polygons).inflated(SCALED_EPSILON));
|
||||||
double threshold = scaled<double>(print_object.config().raft_expansion.value) * 2.;
|
grid.create(raft_polygons, Polylines{}, coord_t(scale_(10.)));
|
||||||
first_layer_move_bounds.erase(std::remove_if(first_layer_move_bounds.begin(), first_layer_move_bounds.end(),
|
SupportElements &first_layer_move_bounds = move_bounds[first_tree_layer];
|
||||||
[&grid, threshold](const SupportElement &el) {
|
double threshold = scaled<double>(print_object.config().raft_expansion.value) * 2.;
|
||||||
coordf_t dist;
|
first_layer_move_bounds.erase(std::remove_if(first_layer_move_bounds.begin(), first_layer_move_bounds.end(),
|
||||||
if (grid.signed_distance_edges(el.state.result_on_layer, threshold, dist)) {
|
[&grid, threshold](const SupportElement &el) {
|
||||||
assert(std::abs(dist) < threshold + SCALED_EPSILON);
|
coordf_t dist;
|
||||||
// Support point is inside the expanded raft, remove it.
|
if (grid.signed_distance_edges(el.state.result_on_layer, threshold, dist)) {
|
||||||
return dist < - 0.;
|
assert(std::abs(dist) < threshold + SCALED_EPSILON);
|
||||||
}
|
// Support point is inside the expanded raft, remove it.
|
||||||
return false;
|
return dist < - 0.;
|
||||||
}), first_layer_move_bounds.end());
|
}
|
||||||
#if 0
|
return false;
|
||||||
// Remove the remaining tips from the raft: Closing operation on tip circles.
|
}), first_layer_move_bounds.end());
|
||||||
if (! first_layer_move_bounds.empty()) {
|
#if 0
|
||||||
const double eps = 0.1;
|
// Remove the remaining tips from the raft: Closing operation on tip circles.
|
||||||
// All tips supporting this layer are expected to have the same radius.
|
if (! first_layer_move_bounds.empty()) {
|
||||||
double radius = config.getRadius(first_layer_move_bounds.front().state);
|
const double eps = 0.1;
|
||||||
// Connect the tips with the following closing radius.
|
// All tips supporting this layer are expected to have the same radius.
|
||||||
double closing_distance = radius;
|
double radius = config.getRadius(first_layer_move_bounds.front().state);
|
||||||
Polygon circle = make_circle(radius + closing_distance, eps);
|
// Connect the tips with the following closing radius.
|
||||||
Polygons circles;
|
double closing_distance = radius;
|
||||||
circles.reserve(first_layer_move_bounds.size());
|
Polygon circle = make_circle(radius + closing_distance, eps);
|
||||||
for (const SupportElement &el : first_layer_move_bounds) {
|
Polygons circles;
|
||||||
circles.emplace_back(circle);
|
circles.reserve(first_layer_move_bounds.size());
|
||||||
circles.back().translate(el.state.result_on_layer);
|
for (const SupportElement &el : first_layer_move_bounds) {
|
||||||
}
|
circles.emplace_back(circle);
|
||||||
raft_polygons = diff(raft_polygons, offset(union_(circles), - closing_distance));
|
circles.back().translate(el.state.result_on_layer);
|
||||||
|
}
|
||||||
|
raft_polygons = diff(raft_polygons, offset(union_(circles), - closing_distance));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4203,79 +4213,90 @@ static void generate_support_areas(Print &print, const BuildVolume &build_volume
|
||||||
std::vector<Polygons> overhangs = generate_overhangs(config, *print.get_object(processing.second.front()), throw_on_cancel);
|
std::vector<Polygons> overhangs = generate_overhangs(config, *print.get_object(processing.second.front()), throw_on_cancel);
|
||||||
|
|
||||||
// ### Precalculate avoidances, collision etc.
|
// ### Precalculate avoidances, collision etc.
|
||||||
size_t num_support_layers = precalculate(print, overhangs, processing.first, processing.second, volumes, throw_on_cancel);
|
|
||||||
if (num_support_layers == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
auto t_precalc = std::chrono::high_resolution_clock::now();
|
|
||||||
|
|
||||||
// value is the area where support may be placed. As this is calculated in CreateLayerPathing it is saved and reused in draw_areas
|
|
||||||
std::vector<SupportElements> move_bounds(num_support_layers);
|
|
||||||
|
|
||||||
// ### Place tips of the support tree
|
|
||||||
SupportGeneratorLayersPtr bottom_contacts(num_support_layers, nullptr);
|
|
||||||
SupportGeneratorLayersPtr top_contacts(num_support_layers, nullptr);
|
|
||||||
SupportGeneratorLayersPtr top_interface_layers(num_support_layers, nullptr);
|
|
||||||
SupportGeneratorLayersPtr intermediate_layers(num_support_layers, nullptr);
|
|
||||||
SupportGeneratorLayerStorage layer_storage;
|
SupportGeneratorLayerStorage layer_storage;
|
||||||
|
SupportGeneratorLayersPtr top_contacts;
|
||||||
|
SupportGeneratorLayersPtr bottom_contacts;
|
||||||
|
SupportGeneratorLayersPtr top_interface_layers;
|
||||||
|
SupportGeneratorLayersPtr intermediate_layers;
|
||||||
|
|
||||||
for (size_t mesh_idx : processing.second)
|
if (size_t num_support_layers = precalculate(print, overhangs, processing.first, processing.second, volumes, throw_on_cancel);
|
||||||
generate_initial_areas(*print.get_object(mesh_idx), volumes, config, overhangs, move_bounds, top_contacts, top_interface_layers, layer_storage, throw_on_cancel);
|
num_support_layers > 0) {
|
||||||
auto t_gen = std::chrono::high_resolution_clock::now();
|
|
||||||
|
|
||||||
#ifdef TREESUPPORT_DEBUG_SVG
|
auto t_precalc = std::chrono::high_resolution_clock::now();
|
||||||
for (size_t layer_idx = 0; layer_idx < move_bounds.size(); ++layer_idx) {
|
|
||||||
Polygons polys;
|
// value is the area where support may be placed. As this is calculated in CreateLayerPathing it is saved and reused in draw_areas
|
||||||
for (auto& area : move_bounds[layer_idx])
|
std::vector<SupportElements> move_bounds(num_support_layers);
|
||||||
append(polys, area.influence_area);
|
|
||||||
if (auto begin = move_bounds[layer_idx].begin(); begin != move_bounds[layer_idx].end())
|
// ### Place tips of the support tree
|
||||||
SVG::export_expolygons(debug_out_path("treesupport-initial_areas-%d.svg", layer_idx),
|
top_contacts .assign(num_support_layers, nullptr);
|
||||||
{ { { union_ex(volumes.getWallRestriction(config.getCollisionRadius(begin->state), layer_idx, begin->state.use_min_xy_dist)) },
|
bottom_contacts .assign(num_support_layers, nullptr);
|
||||||
{ "wall_restricrictions", "gray", 0.5f } },
|
top_interface_layers.assign(num_support_layers, nullptr);
|
||||||
{ { union_ex(polys) }, { "parent", "red", "black", "", scaled<coord_t>(0.1f), 0.5f } } });
|
intermediate_layers .assign(num_support_layers, nullptr);
|
||||||
|
|
||||||
|
for (size_t mesh_idx : processing.second)
|
||||||
|
generate_initial_areas(*print.get_object(mesh_idx), volumes, config, overhangs, move_bounds, top_contacts, top_interface_layers, layer_storage, throw_on_cancel);
|
||||||
|
auto t_gen = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
#ifdef TREESUPPORT_DEBUG_SVG
|
||||||
|
for (size_t layer_idx = 0; layer_idx < move_bounds.size(); ++layer_idx) {
|
||||||
|
Polygons polys;
|
||||||
|
for (auto& area : move_bounds[layer_idx])
|
||||||
|
append(polys, area.influence_area);
|
||||||
|
if (auto begin = move_bounds[layer_idx].begin(); begin != move_bounds[layer_idx].end())
|
||||||
|
SVG::export_expolygons(debug_out_path("treesupport-initial_areas-%d.svg", layer_idx),
|
||||||
|
{ { { union_ex(volumes.getWallRestriction(config.getCollisionRadius(begin->state), layer_idx, begin->state.use_min_xy_dist)) },
|
||||||
|
{ "wall_restricrictions", "gray", 0.5f } },
|
||||||
|
{ { union_ex(polys) }, { "parent", "red", "black", "", scaled<coord_t>(0.1f), 0.5f } } });
|
||||||
|
}
|
||||||
|
#endif // TREESUPPORT_DEBUG_SVG
|
||||||
|
|
||||||
|
// ### Propagate the influence areas downwards. This is an inherently serial operation.
|
||||||
|
create_layer_pathing(volumes, config, move_bounds, throw_on_cancel);
|
||||||
|
auto t_path = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
// ### Set a point in each influence area
|
||||||
|
create_nodes_from_area(volumes, config, move_bounds, throw_on_cancel);
|
||||||
|
auto t_place = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
// ### draw these points as circles
|
||||||
|
|
||||||
|
if (print_object.config().support_material_style == smsTree)
|
||||||
|
draw_areas(*print.get_object(processing.second.front()), volumes, config, overhangs, move_bounds,
|
||||||
|
bottom_contacts, top_contacts, intermediate_layers, layer_storage, throw_on_cancel);
|
||||||
|
else {
|
||||||
|
assert(print_object.config().support_material_style == smsOrganic);
|
||||||
|
indexed_triangle_set branches = draw_branches(*print.get_object(processing.second.front()), volumes, config, move_bounds, throw_on_cancel);
|
||||||
|
// Reduce memory footprint. After this point only slice_branches() will use volumes and from that only collisions with zero radius will be used.
|
||||||
|
volumes.clear_all_but_object_collision();
|
||||||
|
slice_branches(*print.get_object(processing.second.front()), volumes, config, overhangs, move_bounds, branches,
|
||||||
|
bottom_contacts, top_contacts, intermediate_layers, layer_storage, throw_on_cancel);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto t_draw = std::chrono::high_resolution_clock::now();
|
||||||
|
auto dur_pre_gen = 0.001 * std::chrono::duration_cast<std::chrono::microseconds>(t_precalc - t_start).count();
|
||||||
|
auto dur_gen = 0.001 * std::chrono::duration_cast<std::chrono::microseconds>(t_gen - t_precalc).count();
|
||||||
|
auto dur_path = 0.001 * std::chrono::duration_cast<std::chrono::microseconds>(t_path - t_gen).count();
|
||||||
|
auto dur_place = 0.001 * std::chrono::duration_cast<std::chrono::microseconds>(t_place - t_path).count();
|
||||||
|
auto dur_draw = 0.001 * std::chrono::duration_cast<std::chrono::microseconds>(t_draw - t_place).count();
|
||||||
|
auto dur_total = 0.001 * std::chrono::duration_cast<std::chrono::microseconds>(t_draw - t_start).count();
|
||||||
|
BOOST_LOG_TRIVIAL(info) <<
|
||||||
|
"Total time used creating Tree support for the currently grouped meshes: " << dur_total << " ms. "
|
||||||
|
"Different subtasks:\nCalculating Avoidance: " << dur_pre_gen << " ms "
|
||||||
|
"Creating inital influence areas: " << dur_gen << " ms "
|
||||||
|
"Influence area creation: " << dur_path << "ms "
|
||||||
|
"Placement of Points in InfluenceAreas: " << dur_place << "ms "
|
||||||
|
"Drawing result as support " << dur_draw << " ms";
|
||||||
|
// if (config.branch_radius==2121)
|
||||||
|
// BOOST_LOG_TRIVIAL(error) << "Why ask questions when you already know the answer twice.\n (This is not a real bug, please dont report it.)";
|
||||||
|
|
||||||
|
move_bounds.clear();
|
||||||
|
} else {
|
||||||
|
top_contacts.assign(config.raft_layers.size(), nullptr);
|
||||||
|
if (generate_raft_contact(print_object, config, top_contacts, layer_storage) < 0)
|
||||||
|
// No raft.
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
#endif // TREESUPPORT_DEBUG_SVG
|
|
||||||
|
|
||||||
// ### Propagate the influence areas downwards. This is an inherently serial operation.
|
|
||||||
create_layer_pathing(volumes, config, move_bounds, throw_on_cancel);
|
|
||||||
auto t_path = std::chrono::high_resolution_clock::now();
|
|
||||||
|
|
||||||
// ### Set a point in each influence area
|
|
||||||
create_nodes_from_area(volumes, config, move_bounds, throw_on_cancel);
|
|
||||||
auto t_place = std::chrono::high_resolution_clock::now();
|
|
||||||
|
|
||||||
// ### draw these points as circles
|
|
||||||
|
|
||||||
if (print_object.config().support_material_style == smsTree)
|
|
||||||
draw_areas(*print.get_object(processing.second.front()), volumes, config, overhangs, move_bounds,
|
|
||||||
bottom_contacts, top_contacts, intermediate_layers, layer_storage, throw_on_cancel);
|
|
||||||
else {
|
|
||||||
assert(print_object.config().support_material_style == smsOrganic);
|
|
||||||
indexed_triangle_set branches = draw_branches(*print.get_object(processing.second.front()), volumes, config, move_bounds, throw_on_cancel);
|
|
||||||
// Reduce memory footprint. After this point only slice_branches() will use volumes and from that only collisions with zero radius will be used.
|
|
||||||
volumes.clear_all_but_object_collision();
|
|
||||||
slice_branches(*print.get_object(processing.second.front()), volumes, config, overhangs, move_bounds, branches,
|
|
||||||
bottom_contacts, top_contacts, intermediate_layers, layer_storage, throw_on_cancel);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto t_draw = std::chrono::high_resolution_clock::now();
|
|
||||||
auto dur_pre_gen = 0.001 * std::chrono::duration_cast<std::chrono::microseconds>(t_precalc - t_start).count();
|
|
||||||
auto dur_gen = 0.001 * std::chrono::duration_cast<std::chrono::microseconds>(t_gen - t_precalc).count();
|
|
||||||
auto dur_path = 0.001 * std::chrono::duration_cast<std::chrono::microseconds>(t_path - t_gen).count();
|
|
||||||
auto dur_place = 0.001 * std::chrono::duration_cast<std::chrono::microseconds>(t_place - t_path).count();
|
|
||||||
auto dur_draw = 0.001 * std::chrono::duration_cast<std::chrono::microseconds>(t_draw - t_place).count();
|
|
||||||
auto dur_total = 0.001 * std::chrono::duration_cast<std::chrono::microseconds>(t_draw - t_start).count();
|
|
||||||
BOOST_LOG_TRIVIAL(info) <<
|
|
||||||
"Total time used creating Tree support for the currently grouped meshes: " << dur_total << " ms. "
|
|
||||||
"Different subtasks:\nCalculating Avoidance: " << dur_pre_gen << " ms "
|
|
||||||
"Creating inital influence areas: " << dur_gen << " ms "
|
|
||||||
"Influence area creation: " << dur_path << "ms "
|
|
||||||
"Placement of Points in InfluenceAreas: " << dur_place << "ms "
|
|
||||||
"Drawing result as support " << dur_draw << " ms";
|
|
||||||
// if (config.branch_radius==2121)
|
|
||||||
// BOOST_LOG_TRIVIAL(error) << "Why ask questions when you already know the answer twice.\n (This is not a real bug, please dont report it.)";
|
|
||||||
|
|
||||||
move_bounds.clear();
|
|
||||||
|
|
||||||
auto remove_undefined_layers = [](SupportGeneratorLayersPtr &layers) {
|
auto remove_undefined_layers = [](SupportGeneratorLayersPtr &layers) {
|
||||||
layers.erase(std::remove_if(layers.begin(), layers.end(), [](const SupportGeneratorLayer* ptr) { return ptr == nullptr; }), layers.end());
|
layers.erase(std::remove_if(layers.begin(), layers.end(), [](const SupportGeneratorLayer* ptr) { return ptr == nullptr; }), layers.end());
|
||||||
|
@ -4343,7 +4364,9 @@ void fff_tree_support_generate(PrintObject &print_object, std::function<void()>
|
||||||
break;
|
break;
|
||||||
++idx;
|
++idx;
|
||||||
}
|
}
|
||||||
FFFTreeSupport::generate_support_areas(*print_object.print(), BuildVolume(Pointfs{ Vec2d{ -300., -300. }, Vec2d{ -300., +300. }, Vec2d{ +300., +300. }, Vec2d{ +300., -300. } }, 0.), { idx }, throw_on_cancel);
|
FFFTreeSupport::generate_support_areas(*print_object.print(),
|
||||||
|
BuildVolume(Pointfs{ Vec2d{ -300., -300. }, Vec2d{ -300., +300. }, Vec2d{ +300., +300. }, Vec2d{ +300., -300. } }, 0.), { idx },
|
||||||
|
throw_on_cancel);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
Loading…
Reference in a new issue