WIP Tree supports: It compiles, but unfinished, missing pieces.
This commit is contained in:
parent
665d1a94b4
commit
9e6871e5b8
@ -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);
|
||||||
|
@ -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());
|
||||||
|
@ -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,
|
||||||
|
@ -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?
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
@ -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.
|
||||||
|
Loading…
Reference in New Issue
Block a user