WIP Tree supports: It compiles, but unfinished, missing pieces.

This commit is contained in:
Vojtech Bubnik 2022-07-27 10:41:11 +02:00
parent 665d1a94b4
commit 9e6871e5b8
7 changed files with 181 additions and 81 deletions

View File

@ -2130,7 +2130,7 @@ void PrintObject::_generate_support_material()
{ {
if (m_config.support_material_style == smsTree) { if (m_config.support_material_style == smsTree) {
TreeSupport tree_support; TreeSupport tree_support;
tree_support.generateSupportAreas(); tree_support.generateSupportAreas(*this);
} else { } else {
PrintObjectSupportMaterial support_material(this, m_slicing_params); PrintObjectSupportMaterial support_material(this, m_slicing_params);
support_material.generate(*this); support_material.generate(*this);

View File

@ -3912,16 +3912,16 @@ void modulate_extrusion_by_overlapping_layers(
} }
void generate_support_toolpaths( void generate_support_toolpaths(
SupportLayerPtrs &support_layers, SupportLayerPtrs &support_layers,
const PrintObjectConfig &config, const PrintObjectConfig &config,
const SupportParameters &support_params, const SupportParameters &support_params,
const SlicingParameters &slicing_params, const SlicingParameters &slicing_params,
const SupportGeneratorLayersPtr &raft_layers, const SupportGeneratorLayersPtr &raft_layers,
const SupportGeneratorLayersPtr &bottom_contacts, const SupportGeneratorLayersPtr &bottom_contacts,
const SupportGeneratorLayersPtr &top_contacts, const SupportGeneratorLayersPtr &top_contacts,
const SupportGeneratorLayersPtr &intermediate_layers, const SupportGeneratorLayersPtr &intermediate_layers,
const SupportGeneratorLayersPtr &interface_layers, const SupportGeneratorLayersPtr &interface_layers,
const SupportGeneratorLayersPtr &base_interface_layers) const SupportGeneratorLayersPtr &base_interface_layers)
{ {
// loop_interface_processor with a given circle radius. // loop_interface_processor with a given circle radius.
LoopInterfaceProcessor loop_interface_processor(1.5 * support_params.support_material_interface_flow.scaled_width()); LoopInterfaceProcessor loop_interface_processor(1.5 * support_params.support_material_interface_flow.scaled_width());

View File

@ -149,7 +149,7 @@ struct SupportParameters {
// Produce the support G-code. // Produce the support G-code.
// Used by both classic and tree supports. // Used by both classic and tree supports.
static void generate_support_toolpaths( void generate_support_toolpaths(
SupportLayerPtrs &support_layers, SupportLayerPtrs &support_layers,
const PrintObjectConfig &config, const PrintObjectConfig &config,
const SupportParameters &support_params, const SupportParameters &support_params,

View File

@ -45,7 +45,7 @@ TreeSupportMeshGroupSettings::TreeSupportMeshGroupSettings(const PrintObject &pr
this->layer_height = scaled<coord_t>(config.layer_height.value); this->layer_height = scaled<coord_t>(config.layer_height.value);
this->resolution = scaled<coord_t>(print_config.resolution.value); this->resolution = scaled<coord_t>(print_config.resolution.value);
this->min_feature_size = scaled<coord_t>(config.min_feature_size.value); this->min_feature_size = scaled<coord_t>(config.min_feature_size.value);
this->support_angle = M_PI / 2. - config.support_angle * M_PI / 180.; this->support_angle = M_PI / 2. - config.support_material_angle * M_PI / 180.;
this->support_line_width = support_material_flow(&print_object, config.layer_height).scaled_width(); this->support_line_width = support_material_flow(&print_object, config.layer_height).scaled_width();
this->support_roof_line_width = support_material_interface_flow(&print_object, config.layer_height).scaled_width(); this->support_roof_line_width = support_material_interface_flow(&print_object, config.layer_height).scaled_width();
//FIXME add it to SlicingParameters and reuse in both tree and normal supports? //FIXME add it to SlicingParameters and reuse in both tree and normal supports?

View File

@ -372,8 +372,6 @@ private:
calculateCollisionHolefree(std::deque<RadiusLayerPair>{ RadiusLayerPair(key) }); calculateCollisionHolefree(std::deque<RadiusLayerPair>{ RadiusLayerPair(key) });
} }
static Polygons safeOffset(const Polygons& me, coord_t distance, ClipperLib::JoinType jt, coord_t max_safe_step_distance, const Polygons& collision);
/*! /*!
* \brief Creates the areas that have to be avoided by the tree's branches to prevent collision with the model. * \brief Creates the areas that have to be avoided by the tree's branches to prevent collision with the model.
* *
@ -584,6 +582,8 @@ private:
std::unique_ptr<std::mutex> m_critical_progress { std::make_unique<std::mutex>() }; std::unique_ptr<std::mutex> m_critical_progress { std::make_unique<std::mutex>() };
}; };
static Polygons safeOffset(const Polygons& me, coord_t distance, ClipperLib::JoinType jt, coord_t max_safe_step_distance, const Polygons& collision);
} }
#endif //slic3r_TreeModelVolumes_hpp #endif //slic3r_TreeModelVolumes_hpp

View File

@ -7,6 +7,7 @@
// CuraEngine is released under the terms of the AGPLv3 or higher. // CuraEngine is released under the terms of the AGPLv3 or higher.
#include "TreeSupport.hpp" #include "TreeSupport.hpp"
#include "BuildVolume.hpp"
#include "ClipperUtils.hpp" #include "ClipperUtils.hpp"
#include "Fill/Fill.hpp" #include "Fill/Fill.hpp"
#include "Layer.hpp" #include "Layer.hpp"
@ -33,7 +34,7 @@ namespace Slic3r
static constexpr const auto tiny_area_threshold = sqr(scaled<double>(0.001)); static constexpr const auto tiny_area_threshold = sqr(scaled<double>(0.001));
static [[nodiscard]] std::vector<std::pair<TreeSupport::TreeSupportSettings, std::vector<size_t>>> group_meshes(const Print &print, std::vector<size_t> &print_object_ids) static [[nodiscard]] std::vector<std::pair<TreeSupport::TreeSupportSettings, std::vector<size_t>>> group_meshes(const Print &print, const std::vector<size_t> &print_object_ids)
{ {
std::vector<std::pair<TreeSupport::TreeSupportSettings, std::vector<size_t>>> grouped_meshes; std::vector<std::pair<TreeSupport::TreeSupportSettings, std::vector<size_t>>> grouped_meshes;
@ -162,7 +163,19 @@ LayerIndex precalculate(const Print &print, const TreeSupport::TreeSupportSettin
return max_layer; return max_layer;
} }
void TreeSupport::generateSupportAreas(Print &print, const BuildVolume &build_volume, std::vector<size_t> &print_object_ids) //FIXME this is an ugly wrapper interface for a single print object and a phony build volume.
void TreeSupport::generateSupportAreas(PrintObject& print_object)
{
size_t idx = 0;
for (PrintObject *po : print_object.print()->objects()) {
if (po == &print_object)
break;
++ idx;
}
this->generateSupportAreas(*print_object.print(), BuildVolume(Pointfs{ Vec2d{ -1000., -1000. }, Vec2d{ -1000., +1000. }, Vec2d{ +1000., +1000. }, Vec2d{ +1000., -1000. } }, 0.), { idx });
}
void TreeSupport::generateSupportAreas(Print &print, const BuildVolume &build_volume, const std::vector<size_t> &print_object_ids)
{ {
std::vector<std::pair<TreeSupport::TreeSupportSettings, std::vector<size_t>>> grouped_meshes = group_meshes(print, print_object_ids); std::vector<std::pair<TreeSupport::TreeSupportSettings, std::vector<size_t>>> grouped_meshes = group_meshes(print, print_object_ids);
if (grouped_meshes.empty()) if (grouped_meshes.empty())
@ -198,7 +211,8 @@ void TreeSupport::generateSupportAreas(Print &print, const BuildVolume &build_vo
m_progress_multiplier = 1.0 / double(m_grouped_meshes.size()); m_progress_multiplier = 1.0 / double(m_grouped_meshes.size());
m_progress_offset = counter == 0 ? 0 : TREE_PROGRESS_TOTAL * (double(counter) * m_progress_multiplier); m_progress_offset = counter == 0 ? 0 : TREE_PROGRESS_TOTAL * (double(counter) * m_progress_multiplier);
#endif // SLIC3R_TREESUPPORT_PROGRESS #endif // SLIC3R_TREESUPPORT_PROGRESS
m_volumes = TreeModelVolumes(*print.get_object(processing.second.front()), build_volume, m_config.maximum_move_distance, m_config.maximum_move_distance_slow, processing.second.front(), m_progress_multiplier, m_progress_offset, {} /* exclude */); PrintObject &print_object = *print.get_object(processing.second.front());
m_volumes = TreeModelVolumes(print_object, build_volume, m_config.maximum_move_distance, m_config.maximum_move_distance_slow, processing.second.front(), m_progress_multiplier, m_progress_offset, /* additional_excluded_areas */{});
// ### Precalculate avoidances, collision etc. // ### Precalculate avoidances, collision etc.
size_t num_support_layers = precalculate(print, processing.first, processing.second, m_volumes); size_t num_support_layers = precalculate(print, processing.first, processing.second, m_volumes);
@ -208,8 +222,13 @@ void TreeSupport::generateSupportAreas(Print &print, const BuildVolume &build_vo
std::vector<std::set<SupportElement*>> move_bounds(num_support_layers); std::vector<std::set<SupportElement*>> move_bounds(num_support_layers);
// ### Place tips of the support tree // ### 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;
for (size_t mesh_idx : processing.second) for (size_t mesh_idx : processing.second)
generateInitialAreas(*print.get_object(mesh_idx), move_bounds); generateInitialAreas(*print.get_object(mesh_idx), move_bounds, top_contacts, top_interface_layers, layer_storage);
auto t_gen = std::chrono::high_resolution_clock::now(); auto t_gen = std::chrono::high_resolution_clock::now();
// ### Propagate the influence areas downwards. // ### Propagate the influence areas downwards.
@ -221,7 +240,8 @@ void TreeSupport::generateSupportAreas(Print &print, const BuildVolume &build_vo
auto t_place = std::chrono::high_resolution_clock::now(); auto t_place = std::chrono::high_resolution_clock::now();
// ### draw these points as circles // ### draw these points as circles
drawAreas(*print.get_object(processing.second.front()), move_bounds); drawAreas(*print.get_object(processing.second.front()), move_bounds,
bottom_contacts, top_contacts, intermediate_layers, layer_storage);
auto t_draw = std::chrono::high_resolution_clock::now(); 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_pre_gen = 0.001 * std::chrono::duration_cast<std::chrono::microseconds>(t_precalc - t_start).count();
@ -247,6 +267,12 @@ void TreeSupport::generateSupportAreas(Print &print, const BuildVolume &build_vo
} }
} }
// Produce the support G-code.
// Used by both classic and tree supports.
SupportGeneratorLayersPtr raft_layers, interface_layers, base_interface_layers;
generate_support_toolpaths(print_object.support_layers(), print_object.config(), SupportParameters(print_object), print_object.slicing_parameters(),
raft_layers, bottom_contacts, top_contacts, intermediate_layers, interface_layers, base_interface_layers);
++ counter; ++ counter;
} }
@ -759,7 +785,22 @@ static [[nodiscard]] Polygons safeOffsetInc(const Polygons& me, coord_t distance
return union_(ret); return union_(ret);
} }
void TreeSupport::generateInitialAreas(const PrintObject &print_object, std::vector<std::set<SupportElement*>> &move_bounds) // Using the std::deque as an allocator.
inline SupportGeneratorLayer& layer_allocate(
std::deque<SupportGeneratorLayer>& layer_storage,
SupporLayerType layer_type)
{
layer_storage.push_back(SupportGeneratorLayer());
layer_storage.back().layer_type = layer_type;
return layer_storage.back();
}
void TreeSupport::generateInitialAreas(
const PrintObject &print_object,
std::vector<std::set<SupportElement*>> &move_bounds,
SupportGeneratorLayersPtr &top_contacts,
SupportGeneratorLayersPtr &top_interface_layers,
SupportGeneratorLayerStorage &layer_storage)
{ {
Polygon base_circle; Polygon base_circle;
const int base_radius = 10; const int base_radius = 10;
@ -790,12 +831,12 @@ void TreeSupport::generateInitialAreas(const PrintObject &print_object, std::vec
//FIXME //FIXME
size_t num_support_layers = print_object.layer_count(); size_t num_support_layers = print_object.layer_count();
std::vector<std::unordered_set<Point>> already_inserted(num_support_layers - z_distance_delta); std::vector<std::unordered_set<Point, PointHash>> already_inserted(num_support_layers - z_distance_delta);
std::mutex critical_sections; std::mutex critical_sections;
tbb::parallel_for(tbb::blocked_range<size_t>(1, num_support_layers - z_distance_delta), tbb::parallel_for(tbb::blocked_range<size_t>(1, num_support_layers - z_distance_delta),
[this, &print_object, &mesh_config, &mesh_group_settings, &support_params, z_distance_delta, xy_overrides_z, force_tip_to_roof, roof_enabled, support_roof_layers, extra_outset, circle_length_to_half_linewidth_change, connect_length, max_overhang_insert_lag, [this, &print_object, &mesh_config, &mesh_group_settings, &support_params, z_distance_delta, xy_overrides_z, force_tip_to_roof, roof_enabled, support_roof_layers, extra_outset, circle_length_to_half_linewidth_change, connect_length, max_overhang_insert_lag,
&base_circle, &critical_sections, &already_inserted, &base_circle, &critical_sections, &top_contacts, &layer_storage, &already_inserted,
&move_bounds, &base_radius](const tbb::blocked_range<size_t> &range) { &move_bounds, &base_radius](const tbb::blocked_range<size_t> &range) {
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
if (! layer_has_overhangs(*print_object.get_layer(layer_idx + z_distance_delta))) if (! layer_has_overhangs(*print_object.get_layer(layer_idx + z_distance_delta)))
@ -883,8 +924,10 @@ void TreeSupport::generateInitialAreas(const PrintObject &print_object, std::vec
added_roofs = union_(added_roofs); added_roofs = union_(added_roofs);
{ {
std::lock_guard<std::mutex> critical_section_storage(critical_sections); std::lock_guard<std::mutex> critical_section_storage(critical_sections);
//FIXME store top support interface areas or maybe hatch them? SupportGeneratorLayer *&l = top_contacts[insert_layer_idx - dtt_roof_tip];
// append(storage.support.supportLayers[insert_layer_idx - dtt_roof_tip].support_roof, added_roofs); if (l == nullptr)
l = &layer_allocate(layer_storage, SupporLayerType::TopContact);
append(l->polygons, std::move(added_roofs));
} }
} }
@ -1023,9 +1066,13 @@ void TreeSupport::generateInitialAreas(const PrintObject &print_object, std::vec
{ {
std::lock_guard<std::mutex> critical_section_storage(critical_sections); std::lock_guard<std::mutex> critical_section_storage(critical_sections);
//FIXME store support areas or hatch the lines? for (size_t idx = 0; idx < dtt_roof; idx++) {
// for (size_t idx = 0; idx < dtt_roof; idx++) SupportGeneratorLayer *&l = top_contacts[layer_idx - idx];
// append(storage.support.supportLayers[layer_idx - idx].support_roof, added_roofs[idx]); // will be unioned in finalizeInterfaceAndSupportAreas if (l == nullptr)
l = &layer_allocate(layer_storage, SupporLayerType::TopContact);
// will be unioned in finalizeInterfaceAndSupportAreas
append(l->polygons, std::move(added_roofs[idx]));
}
} }
if (overhang_lines.empty()) { if (overhang_lines.empty()) {
@ -1054,8 +1101,10 @@ void TreeSupport::generateInitialAreas(const PrintObject &print_object, std::vec
if (int(dtt_roof) >= layer_idx && roof_allowed_for_this_part) { // reached buildplate if (int(dtt_roof) >= layer_idx && roof_allowed_for_this_part) { // reached buildplate
std::lock_guard<std::mutex> critical_section_storage(critical_sections); std::lock_guard<std::mutex> critical_section_storage(critical_sections);
//FIXME store support roofs SupportGeneratorLayer*& l = top_contacts[0];
// append(storage.support.supportLayers[0].support_roof, overhang_outset); if (l == nullptr)
l = &layer_allocate(layer_storage, SupporLayerType::TopContact);
append(l->polygons, std::move(overhang_outset));
} else // normal trees have to be generated } else // normal trees have to be generated
addLinesAsInfluenceAreas(overhang_lines, force_tip_to_roof ? support_roof_layers - dtt_roof : 0, layer_idx - dtt_roof, dtt_roof > 0, roof_enabled ? support_roof_layers - dtt_roof : 0); addLinesAsInfluenceAreas(overhang_lines, force_tip_to_roof ? support_roof_layers - dtt_roof : 0, layer_idx - dtt_roof, dtt_roof > 0, roof_enabled ? support_roof_layers - dtt_roof : 0);
} }
@ -1107,7 +1156,7 @@ static unsigned int moveInside(const Polygons &polygons, Point &from, int distan
ret = x; ret = x;
else { else {
Vec2d abd = ab.cast<double>(); Vec2d abd = ab.cast<double>();
Vec2d p1p2 = p1 - p0; Vec2d p1p2 = (p1 - p0).cast<double>();
double lab = abd.norm(); double lab = abd.norm();
double lp1p2 = p1p2.norm(); double lp1p2 = p1p2.norm();
// inward direction irrespective of sign of [distance] // inward direction irrespective of sign of [distance]
@ -1661,7 +1710,7 @@ void TreeSupport::increaseAreas(std::unordered_map<SupportElement, Polygons>& to
for (AreaIncreaseSettings settings : order) for (AreaIncreaseSettings settings : order)
{ {
new_order.emplace_back(settings); new_order.emplace_back(settings);
new_order.emplace_back(settings.type, settings.increase_speed, settings.increase_radius, settings.no_error, use_min_radius, settings.move); new_order.push_back({ settings.type, settings.increase_speed, settings.increase_radius, settings.no_error, use_min_radius, settings.move });
} }
order = new_order; order = new_order;
} }
@ -2260,7 +2309,15 @@ void TreeSupport::dropNonGraciousAreas(
}); });
} }
void TreeSupport::finalizeInterfaceAndSupportAreas(const PrintObject &print_object, std::vector<Polygons>& support_layer_storage, std::vector<Polygons>& support_roof_storage) void TreeSupport::finalizeInterfaceAndSupportAreas(
const PrintObject &print_object,
std::vector<Polygons> &support_layer_storage,
std::vector<Polygons> &support_roof_storage,
SupportGeneratorLayersPtr &bottom_contacts,
SupportGeneratorLayersPtr &top_contacts,
SupportGeneratorLayersPtr &intermediate_layers,
SupportGeneratorLayerStorage &layer_storage)
{ {
InterfacePreference interface_pref = m_config.interface_preference; // InterfacePreference::SUPPORT_LINES_OVERWRITE_INTERFACE; InterfacePreference interface_pref = m_config.interface_preference; // InterfacePreference::SUPPORT_LINES_OVERWRITE_INTERFACE;
@ -2278,46 +2335,57 @@ void TreeSupport::finalizeInterfaceAndSupportAreas(const PrintObject &print_obje
// simplify a bit, to ensure the output does not contain outrageous amounts of vertices. Should not be necessary, just a precaution. // 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(m_config.resolution))); support_layer_storage[layer_idx] = polygons_simplify(support_layer_storage[layer_idx], std::min(scaled<double>(0.03), double(m_config.resolution)));
// Subtract support lines of the branches from the roof // Subtract support lines of the branches from the roof
storage.support.supportLayers[layer_idx].support_roof = union_(storage.support.supportLayers[layer_idx].support_roof, support_roof_storage[layer_idx]); SupportGeneratorLayer*& support_roof = top_contacts[layer_idx];
if (!storage.support.supportLayers[layer_idx].support_roof.empty() && if (! support_roof_storage[layer_idx].empty() || support_roof != nullptr) {
area(intersection(support_layer_storage[layer_idx], storage.support.supportLayers[layer_idx].support_roof)) > tiny_area_threshold) { if (support_roof == nullptr) {
switch (interface_pref) { support_roof = &layer_allocate(layer_storage, SupporLayerType::TopContact);
case InterfacePreference::INTERFACE_AREA_OVERWRITES_SUPPORT: support_roof->polygons = union_(support_roof_storage[layer_idx]);
support_layer_storage[layer_idx] = diff(support_layer_storage[layer_idx], storage.support.supportLayers[layer_idx].support_roof); } else
break; support_roof->polygons = union_(support_roof->polygons, support_roof_storage[layer_idx]);
case InterfacePreference::SUPPORT_AREA_OVERWRITES_INTERFACE:
storage.support.supportLayers[layer_idx].support_roof = diff(storage.support.supportLayers[layer_idx].support_roof, support_layer_storage[layer_idx]); if (! support_roof->polygons.empty() &&
break; area(intersection(support_layer_storage[layer_idx], support_roof->polygons)) > tiny_area_threshold) {
//FIXME switch (interface_pref) {
#if 0 case InterfacePreference::INTERFACE_AREA_OVERWRITES_SUPPORT:
case InterfacePreference::INTERFACE_LINES_OVERWRITE_SUPPORT: support_layer_storage[layer_idx] = diff(support_layer_storage[layer_idx], support_roof->polygons);
{ break;
// Hatch the support roof interfaces, offset them by their line width and subtract them from support base. case InterfacePreference::SUPPORT_AREA_OVERWRITES_INTERFACE:
Polygons interface_lines = offset(to_polylines( support_roof->polygons = diff(support_roof->polygons, support_layer_storage[layer_idx]);
generateSupportInfillLines(storage.support.supportLayers[layer_idx].support_roof, true, layer_idx, m_config.support_roof_line_distance)), break;
m_config.support_roof_line_width / 2); //FIXME
support_layer_storage[layer_idx] = diff(support_layer_storage[layer_idx], interface_lines); #if 0
break; case InterfacePreference::INTERFACE_LINES_OVERWRITE_SUPPORT:
{
// Hatch the support roof interfaces, offset them by their line width and subtract them from support base.
Polygons interface_lines = offset(to_polylines(
generateSupportInfillLines(support_roof->polygons, true, layer_idx, m_config.support_roof_line_distance)),
m_config.support_roof_line_width / 2);
support_layer_storage[layer_idx] = diff(support_layer_storage[layer_idx], interface_lines);
break;
}
case InterfacePreference::SUPPORT_LINES_OVERWRITE_INTERFACE:
{
// Hatch the support roof interfaces, offset them by their line width and subtract them from support base.
Polygons tree_lines = union_(offset(to_polylines(
generateSupportInfillLines(support_layer_storage[layer_idx], false, layer_idx, m_config.support_line_distance, true)),
m_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);
break;
}
#endif
case InterfacePreference::NOTHING:
break;
} }
case InterfacePreference::SUPPORT_LINES_OVERWRITE_INTERFACE:
{
// Hatch the support roof interfaces, offset them by their line width and subtract them from support base.
Polygons tree_lines = union_(offset(to_polylines(
generateSupportInfillLines(support_layer_storage[layer_idx], false, layer_idx, m_config.support_line_distance, true)),
m_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.
storage.support.supportLayers[layer_idx].support_roof = diff(storage.support.supportLayers[layer_idx].support_roof, tree_lines);
break;
}
#endif
case InterfacePreference::NOTHING:
break;
} }
} }
// Subtract support floors from the support area and add them to the support floor instead. // Subtract support floors from the support area and add them to the support floor instead.
if (m_config.support_bottom_layers > 0 && !support_layer_storage[layer_idx].empty()) { if (m_config.support_bottom_layers > 0 && !support_layer_storage[layer_idx].empty()) {
Polygons floor_layer = storage.support.supportLayers[layer_idx].support_bottom; SupportGeneratorLayer*& support_bottom = bottom_contacts[layer_idx];
if (support_bottom == nullptr)
support_bottom = &layer_allocate(layer_storage, SupporLayerType::BottomContact);
Polygons floor_layer = std::move(support_bottom->polygons);
Polygons layer_outset = diff(offset(support_layer_storage[layer_idx], m_config.support_bottom_offset), m_volumes.getCollision(0, layer_idx, false)); Polygons layer_outset = diff(offset(support_layer_storage[layer_idx], m_config.support_bottom_offset), m_volumes.getCollision(0, layer_idx, false));
size_t layers_below = 0; size_t layers_below = 0;
while (layers_below <= m_config.support_bottom_layers) { while (layers_below <= m_config.support_bottom_layers) {
@ -2330,13 +2398,16 @@ void TreeSupport::finalizeInterfaceAndSupportAreas(const PrintObject &print_obje
else else
break; break;
} }
floor_layer = union_(floor_layer); support_bottom->polygons = union_(floor_layer);
storage.support.supportLayers[layer_idx].support_bottom = union_(storage.support.supportLayers[layer_idx].support_bottom, floor_layer); support_layer_storage[layer_idx] = diff(support_layer_storage[layer_idx], offset(support_bottom->polygons, scaled<float>(0.01))); // Subtract the support floor from the normal support.
support_layer_storage[layer_idx] = diff(support_layer_storage[layer_idx], offset(floor_layer, scaled<float>(0.01))); // Subtract the support floor from the normal support.
} }
for (const ExPolygon &part : union_ex(support_layer_storage[layer_idx])) // Convert every part into a PolygonsPart for the support. {
storage.support.supportLayers[layer_idx].support_infill_parts.emplace_back(part, m_config.support_line_width, m_config.support_wall_count); SupportGeneratorLayer *&l = intermediate_layers[layer_idx];
if (l == nullptr)
l = &layer_allocate(layer_storage, SupporLayerType::Base);
append(l->polygons, union_(support_layer_storage[layer_idx]));
}
#ifdef SLIC3R_TREESUPPORTS_PROGRESS #ifdef SLIC3R_TREESUPPORTS_PROGRESS
{ {
@ -2356,7 +2427,14 @@ void TreeSupport::finalizeInterfaceAndSupportAreas(const PrintObject &print_obje
}); });
} }
void TreeSupport::drawAreas(PrintObject &print_object, std::vector<std::set<SupportElement*>> &move_bounds) void TreeSupport::drawAreas(
PrintObject &print_object,
std::vector<std::set<SupportElement*>> &move_bounds,
SupportGeneratorLayersPtr &bottom_contacts,
SupportGeneratorLayersPtr &top_contacts,
SupportGeneratorLayersPtr &intermediate_layers,
SupportGeneratorLayerStorage &layer_storage)
{ {
std::vector<Polygons> support_layer_storage(move_bounds.size()); std::vector<Polygons> support_layer_storage(move_bounds.size());
std::vector<Polygons> support_roof_storage(move_bounds.size()); std::vector<Polygons> support_roof_storage(move_bounds.size());
@ -2396,7 +2474,8 @@ void TreeSupport::drawAreas(PrintObject &print_object, std::vector<std::set<Supp
for (std::pair<SupportElement*, Polygons> data_pair : layer_tree_polygons[layer_idx]) for (std::pair<SupportElement*, Polygons> data_pair : layer_tree_polygons[layer_idx])
append(data_pair.first->missing_roof_layers > data_pair.first->distance_to_top ? support_roof_storage[layer_idx] : support_layer_storage[layer_idx], std::move(data_pair.second)); append(data_pair.first->missing_roof_layers > data_pair.first->distance_to_top ? support_roof_storage[layer_idx] : support_layer_storage[layer_idx], std::move(data_pair.second));
finalizeInterfaceAndSupportAreas(print_object, support_layer_storage, support_roof_storage); finalizeInterfaceAndSupportAreas(print_object, support_layer_storage, support_roof_storage,
bottom_contacts, top_contacts, intermediate_layers, layer_storage);
auto t_end = std::chrono::high_resolution_clock::now(); auto t_end = std::chrono::high_resolution_clock::now();
auto dur_gen_tips = 0.001 * std::chrono::duration_cast<std::chrono::microseconds>(t_generate - t_start).count(); auto dur_gen_tips = 0.001 * std::chrono::duration_cast<std::chrono::microseconds>(t_generate - t_start).count();

View File

@ -48,8 +48,9 @@ using LayerIndex = size_t;
//FIXME //FIXME
class Print; class Print;
class PrintObject; class PrintObject;
class SliceDataStorage; class SupportGeneratorLayer;
using SupportGeneratorLayerStorage = std::deque<SupportGeneratorLayer>;
using SupportGeneratorLayersPtr = std::vector<SupportGeneratorLayer*>;
/*! /*!
* \brief Generates a tree structure to support your models. * \brief Generates a tree structure to support your models.
*/ */
@ -70,7 +71,7 @@ public:
/*! /*!
* \brief Creates an instance of the tree support generator. * \brief Creates an instance of the tree support generator.
*/ */
TreeSupport(); TreeSupport() = default;
/*! /*!
* \brief Create the areas that need support. * \brief Create the areas that need support.
@ -79,7 +80,8 @@ public:
* \param storage The data storage where the mesh data is gotten from and * \param storage The data storage where the mesh data is gotten from and
* where the resulting support areas are stored. * where the resulting support areas are stored.
*/ */
void generateSupportAreas(Print &print, const BuildVolume &build_volume, std::vector<size_t>& print_object_ids); void generateSupportAreas(Print &print, const BuildVolume &build_volume, const std::vector<size_t>& print_object_ids);
void generateSupportAreas(PrintObject &print_object);
//todo Remove! Only relevant for public BETA! //todo Remove! Only relevant for public BETA!
@ -711,7 +713,11 @@ private:
* \param move_bounds[out] Storage for the influence areas. * \param move_bounds[out] Storage for the influence areas.
* \param storage[in] Background storage, required for adding roofs. * \param storage[in] Background storage, required for adding roofs.
*/ */
void generateInitialAreas(const PrintObject &print_object, std::vector<std::set<SupportElement*>> &move_bounds); void generateInitialAreas(const PrintObject &print_object,
std::vector<std::set<SupportElement*>> &move_bounds,
SupportGeneratorLayersPtr &top_contacts,
SupportGeneratorLayersPtr &top_interface_layers,
SupportGeneratorLayerStorage &layer_storage);
/*! /*!
* \brief Checks if an influence area contains a valid subsection and returns the corresponding metadata and the new Influence area. * \brief Checks if an influence area contains a valid subsection and returns the corresponding metadata and the new Influence area.
@ -818,7 +824,15 @@ private:
* \param support_roof_storage[in] Areas where support was replaced with roof. * \param support_roof_storage[in] Areas where support was replaced with roof.
* \param storage[in,out] The storage where the support should be stored. * \param storage[in,out] The storage where the support should be stored.
*/ */
void finalizeInterfaceAndSupportAreas(const PrintObject &print_object, std::vector<Polygons>& support_layer_storage, std::vector<Polygons>& support_roof_storage); void finalizeInterfaceAndSupportAreas(
const PrintObject &print_object,
std::vector<Polygons> &support_layer_storage,
std::vector<Polygons> &support_roof_storage,
SupportGeneratorLayersPtr &bottom_contacts,
SupportGeneratorLayersPtr &top_contacts,
SupportGeneratorLayersPtr &intermediate_layers,
SupportGeneratorLayerStorage &layer_storage);
/*! /*!
* \brief Draws circles around result_on_layer points of the influence areas and applies some post processing. * \brief Draws circles around result_on_layer points of the influence areas and applies some post processing.
@ -826,7 +840,14 @@ private:
* \param move_bounds[in] All currently existing influence areas * \param move_bounds[in] All currently existing influence areas
* \param storage[in,out] The storage where the support should be stored. * \param storage[in,out] The storage where the support should be stored.
*/ */
void drawAreas(PrintObject &print_object, std::vector<std::set<SupportElement*>>& move_bounds); void drawAreas(
PrintObject &print_object,
std::vector<std::set<SupportElement*>> &move_bounds,
SupportGeneratorLayersPtr &bottom_contacts,
SupportGeneratorLayersPtr &top_contacts,
SupportGeneratorLayersPtr &intermediate_layers,
SupportGeneratorLayerStorage &layer_storage);
/*! /*!
* \brief Settings with the indexes of meshes that use these settings. * \brief Settings with the indexes of meshes that use these settings.