mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-13 19:35:57 +08:00
WIP: Organic Supports & Raft
Object is lifted, trees are routed to the ground.
This commit is contained in:
parent
b767c76adb
commit
825c954b44
@ -2226,9 +2226,11 @@ void PrintObject::combine_infill()
|
||||
|
||||
void PrintObject::_generate_support_material()
|
||||
{
|
||||
if (m_config.support_material_style == smsTree || m_config.support_material_style == smsOrganic) {
|
||||
if (this->has_support() && (m_config.support_material_style == smsTree || m_config.support_material_style == smsOrganic)) {
|
||||
fff_tree_support_generate(*this, std::function<void()>([this](){ this->throw_if_canceled(); }));
|
||||
} else {
|
||||
// If support style is set to Organic however only raft will be built but no support,
|
||||
// build snug raft instead.
|
||||
PrintObjectSupportMaterial support_material(this, m_slicing_params);
|
||||
support_material.generate(*this);
|
||||
}
|
||||
|
@ -799,10 +799,6 @@ public:
|
||||
)
|
||||
{
|
||||
switch (m_style) {
|
||||
case smsTree:
|
||||
case smsOrganic:
|
||||
assert(false);
|
||||
[[fallthrough]];
|
||||
case smsGrid:
|
||||
{
|
||||
#ifdef SUPPORT_USE_AGG_RASTERIZER
|
||||
@ -893,6 +889,10 @@ public:
|
||||
polygons_rotate(out, m_support_angle);
|
||||
return out;
|
||||
}
|
||||
case smsTree:
|
||||
case smsOrganic:
|
||||
// assert(false);
|
||||
[[fallthrough]];
|
||||
case smsSnug:
|
||||
// Merge the support polygons by applying morphological closing and inwards smoothing.
|
||||
auto closing_distance = scaled<float>(m_support_material_closing_radius);
|
||||
@ -1763,7 +1763,7 @@ static inline void fill_contact_layer(
|
||||
#endif // SLIC3R_DEBUG
|
||||
));
|
||||
// 2) infill polygons, expand them by half the extrusion width + a tiny bit of extra.
|
||||
bool reduce_interfaces = object_config.support_material_style.value != smsSnug && layer_id > 0 && !slicing_params.soluble_interface;
|
||||
bool reduce_interfaces = object_config.support_material_style.value == smsGrid && layer_id > 0 && !slicing_params.soluble_interface;
|
||||
if (reduce_interfaces) {
|
||||
// Reduce the amount of dense interfaces: Do not generate dense interfaces below overhangs with 60% overhang of the extrusions.
|
||||
Polygons dense_interface_polygons = diff(overhang_polygons, lower_layer_polygons_for_dense_interface());
|
||||
@ -3045,7 +3045,7 @@ std::pair<SupportGeneratorLayersPtr, SupportGeneratorLayersPtr> PrintObjectSuppo
|
||||
m_object_config->support_material_interface_extruder.value > 0 && m_print_config->filament_soluble.get_at(m_object_config->support_material_interface_extruder.value - 1) &&
|
||||
// Base extruder: Either "print with active extruder" not soluble.
|
||||
(m_object_config->support_material_extruder.value == 0 || ! m_print_config->filament_soluble.get_at(m_object_config->support_material_extruder.value - 1));
|
||||
bool snug_supports = m_object_config->support_material_style.value == smsSnug;
|
||||
bool snug_supports = m_object_config->support_material_style.value != smsGrid;
|
||||
int num_interface_layers_top = m_object_config->support_material_interface_layers;
|
||||
int num_interface_layers_bottom = m_object_config->support_material_bottom_interface_layers;
|
||||
if (num_interface_layers_bottom < 0)
|
||||
@ -4227,7 +4227,7 @@ void generate_support_toolpaths(
|
||||
}
|
||||
|
||||
// Insert the raft base layers.
|
||||
size_t n_raft_layers = size_t(std::max(0, int(slicing_params.raft_layers()) - 1));
|
||||
auto n_raft_layers = std::min<size_t>(support_layers.size(), std::max(0, int(slicing_params.raft_layers()) - 1));
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, n_raft_layers),
|
||||
[&support_layers, &raft_layers, &config, &support_params, &slicing_params,
|
||||
&bbox_object, raft_angle_1st_layer, raft_angle_base, raft_angle_interface, link_max_length_factor]
|
||||
@ -4356,7 +4356,7 @@ void generate_support_toolpaths(
|
||||
{
|
||||
SupportLayer &support_layer = *support_layers[support_layer_id];
|
||||
LayerCache &layer_cache = layer_caches[support_layer_id];
|
||||
float interface_angle_delta = config.support_material_style.value == smsSnug || config.support_material_style.value == smsTree || config.support_material_style.value == smsOrganic ?
|
||||
float interface_angle_delta = config.support_material_style.value != smsGrid ?
|
||||
(support_layer.interface_id() & 1) ? float(- M_PI / 4.) : float(+ M_PI / 4.) :
|
||||
0;
|
||||
|
||||
|
@ -13,7 +13,7 @@ class PrintObjectConfig;
|
||||
|
||||
// Support layer type to be used by SupportGeneratorLayer. This type carries a much more detailed information
|
||||
// about the support layer type than the final support layers stored in a PrintObject.
|
||||
enum SupporLayerType {
|
||||
enum class SupporLayerType {
|
||||
Unknown = 0,
|
||||
// Ratft base layer, to be printed with the support material.
|
||||
RaftBase,
|
||||
|
@ -158,14 +158,24 @@ TreeModelVolumes::TreeModelVolumes(
|
||||
{
|
||||
m_anti_overhang = print_object.slice_support_blockers();
|
||||
TreeSupportMeshGroupSettings mesh_settings(print_object);
|
||||
m_layer_outlines.emplace_back(mesh_settings, std::vector<Polygons>{});
|
||||
const TreeSupportSettings config{ mesh_settings, print_object.slicing_parameters() };
|
||||
m_current_min_xy_dist = config.xy_min_distance;
|
||||
m_current_min_xy_dist_delta = config.xy_distance - m_current_min_xy_dist;
|
||||
assert(m_current_min_xy_dist_delta >= 0);
|
||||
m_increase_until_radius = config.increase_radius_until_radius;
|
||||
m_radius_0 = config.getRadius(0);
|
||||
m_raft_layers = config.raft_layers;
|
||||
m_current_outline_idx = 0;
|
||||
|
||||
m_layer_outlines.emplace_back(mesh_settings, std::vector<Polygons>{});
|
||||
std::vector<Polygons> &outlines = m_layer_outlines.front().second;
|
||||
outlines.assign(print_object.layer_count(), Polygons{});
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, print_object.layer_count(), std::min<size_t>(1, std::max<size_t>(16, print_object.layer_count() / (8 * tbb::this_task_arena::max_concurrency())))),
|
||||
size_t num_raft_layers = m_raft_layers.size();
|
||||
size_t num_layers = print_object.layer_count() + num_raft_layers;
|
||||
outlines.assign(num_layers, Polygons{});
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(num_raft_layers, num_layers, std::min<size_t>(1, std::max<size_t>(16, num_layers / (8 * tbb::this_task_arena::max_concurrency())))),
|
||||
[&](const tbb::blocked_range<size_t> &range) {
|
||||
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx)
|
||||
outlines[layer_idx] = to_polygons(expolygons_simplify(print_object.get_layer(layer_idx)->lslices, mesh_settings.resolution));
|
||||
outlines[layer_idx] = to_polygons(expolygons_simplify(print_object.get_layer(layer_idx - num_raft_layers)->lslices, mesh_settings.resolution));
|
||||
});
|
||||
}
|
||||
#endif
|
||||
@ -177,13 +187,6 @@ TreeModelVolumes::TreeModelVolumes(
|
||||
m_min_resolution = std::min(m_min_resolution, data_pair.first.resolution);
|
||||
}
|
||||
|
||||
const TreeSupportSettings config{ m_layer_outlines[m_current_outline_idx].first };
|
||||
m_current_min_xy_dist = config.xy_min_distance;
|
||||
m_current_min_xy_dist_delta = config.xy_distance - m_current_min_xy_dist;
|
||||
assert(m_current_min_xy_dist_delta >= 0);
|
||||
m_increase_until_radius = config.increase_radius_until_radius;
|
||||
m_radius_0 = config.getRadius(0);
|
||||
|
||||
#if 0
|
||||
for (size_t mesh_idx = 0; mesh_idx < storage.meshes.size(); mesh_idx++) {
|
||||
SliceMeshStorage mesh = storage.meshes[mesh_idx];
|
||||
@ -214,7 +217,7 @@ TreeModelVolumes::TreeModelVolumes(
|
||||
#endif
|
||||
}
|
||||
|
||||
void TreeModelVolumes::precalculate(const coord_t max_layer, std::function<void()> throw_on_cancel)
|
||||
void TreeModelVolumes::precalculate(const PrintObject& print_object, const coord_t max_layer, std::function<void()> throw_on_cancel)
|
||||
{
|
||||
auto t_start = std::chrono::high_resolution_clock::now();
|
||||
m_precalculated = true;
|
||||
@ -222,7 +225,7 @@ void TreeModelVolumes::precalculate(const coord_t max_layer, std::function<void(
|
||||
// Get the config corresponding to one mesh that is in the current group. Which one has to be irrelevant.
|
||||
// Not the prettiest way to do this, but it ensures some calculations that may be a bit more complex
|
||||
// like inital layer diameter are only done in once.
|
||||
TreeSupportSettings config(m_layer_outlines[m_current_outline_idx].first);
|
||||
TreeSupportSettings config(m_layer_outlines[m_current_outline_idx].first, print_object.slicing_parameters());
|
||||
|
||||
{
|
||||
// calculate which radius each layer in the tip may have.
|
||||
|
@ -244,7 +244,7 @@ public:
|
||||
* Knowledge about branch angle is used to only calculate avoidances and collisions that may actually be needed.
|
||||
* Not calling precalculate() will cause the class to lazily calculate avoidances and collisions as needed, which will be a lot slower on systems with more then one or two cores!
|
||||
*/
|
||||
void precalculate(const coord_t max_layer, std::function<void()> throw_on_cancel);
|
||||
void precalculate(const PrintObject& print_object, const coord_t max_layer, std::function<void()> throw_on_cancel);
|
||||
|
||||
/*!
|
||||
* \brief Provides the areas that have to be avoided by the tree's branches to prevent collision with the model on this layer.
|
||||
@ -618,6 +618,9 @@ private:
|
||||
*/
|
||||
coord_t m_radius_0;
|
||||
|
||||
// Z heights of the raft layers (additional layers below the object, last raft layer aligned with the bottom of the first object layer).
|
||||
std::vector<double> m_raft_layers;
|
||||
|
||||
/*!
|
||||
* \brief Caches for the collision, avoidance and areas on the model where support can be placed safely
|
||||
* at given radius and layer indices.
|
||||
|
@ -59,6 +59,85 @@ namespace Slic3r
|
||||
namespace FFFTreeSupport
|
||||
{
|
||||
|
||||
TreeSupportSettings::TreeSupportSettings(const TreeSupportMeshGroupSettings& mesh_group_settings, const SlicingParameters &slicing_params)
|
||||
: angle(mesh_group_settings.support_tree_angle),
|
||||
angle_slow(mesh_group_settings.support_tree_angle_slow),
|
||||
support_line_width(mesh_group_settings.support_line_width),
|
||||
layer_height(mesh_group_settings.layer_height),
|
||||
branch_radius(mesh_group_settings.support_tree_branch_diameter / 2),
|
||||
min_radius(mesh_group_settings.support_tree_tip_diameter / 2), // The actual radius is 50 microns larger as the resulting branches will be increased by 50 microns to avoid rounding errors effectively increasing the xydistance
|
||||
maximum_move_distance((angle < M_PI / 2.) ? (coord_t)(tan(angle) * layer_height) : std::numeric_limits<coord_t>::max()),
|
||||
maximum_move_distance_slow((angle_slow < M_PI / 2.) ? (coord_t)(tan(angle_slow) * layer_height) : std::numeric_limits<coord_t>::max()),
|
||||
support_bottom_layers(mesh_group_settings.support_bottom_enable ? (mesh_group_settings.support_bottom_height + layer_height / 2) / layer_height : 0),
|
||||
tip_layers(std::max((branch_radius - min_radius) / (support_line_width / 3), branch_radius / layer_height)), // Ensure lines always stack nicely even if layer height is large
|
||||
diameter_angle_scale_factor(sin(mesh_group_settings.support_tree_branch_diameter_angle) * layer_height / branch_radius),
|
||||
max_to_model_radius_increase(mesh_group_settings.support_tree_max_diameter_increase_by_merges_when_support_to_model / 2),
|
||||
min_dtt_to_model(round_up_divide(mesh_group_settings.support_tree_min_height_to_model, layer_height)),
|
||||
increase_radius_until_radius(mesh_group_settings.support_tree_branch_diameter / 2),
|
||||
increase_radius_until_layer(increase_radius_until_radius <= branch_radius ? tip_layers * (increase_radius_until_radius / branch_radius) : (increase_radius_until_radius - branch_radius) / (branch_radius * diameter_angle_scale_factor)),
|
||||
support_rests_on_model(! mesh_group_settings.support_material_buildplate_only),
|
||||
xy_distance(mesh_group_settings.support_xy_distance),
|
||||
xy_min_distance(std::min(mesh_group_settings.support_xy_distance, mesh_group_settings.support_xy_distance_overhang)),
|
||||
bp_radius(mesh_group_settings.support_tree_bp_diameter / 2),
|
||||
diameter_scale_bp_radius(std::min(sin(0.7) * layer_height / branch_radius, 1.0 / (branch_radius / (support_line_width / 2.0)))), // Either 40? or as much as possible so that 2 lines will overlap by at least 50%, whichever is smaller.
|
||||
z_distance_top_layers(round_up_divide(mesh_group_settings.support_top_distance, layer_height)),
|
||||
z_distance_bottom_layers(round_up_divide(mesh_group_settings.support_bottom_distance, layer_height)),
|
||||
performance_interface_skip_layers(round_up_divide(mesh_group_settings.support_interface_skip_height, layer_height)),
|
||||
// support_infill_angles(mesh_group_settings.support_infill_angles),
|
||||
support_roof_angles(mesh_group_settings.support_roof_angles),
|
||||
roof_pattern(mesh_group_settings.support_roof_pattern),
|
||||
support_pattern(mesh_group_settings.support_pattern),
|
||||
support_roof_line_width(mesh_group_settings.support_roof_line_width),
|
||||
support_line_spacing(mesh_group_settings.support_line_spacing),
|
||||
support_bottom_offset(mesh_group_settings.support_bottom_offset),
|
||||
support_wall_count(mesh_group_settings.support_wall_count),
|
||||
resolution(mesh_group_settings.resolution),
|
||||
support_roof_line_distance(mesh_group_settings.support_roof_line_distance), // in the end the actual infill has to be calculated to subtract interface from support areas according to interface_preference.
|
||||
settings(mesh_group_settings),
|
||||
min_feature_size(mesh_group_settings.min_feature_size)
|
||||
{
|
||||
layer_start_bp_radius = (bp_radius - branch_radius) / (branch_radius * diameter_scale_bp_radius);
|
||||
|
||||
if (TreeSupportSettings::soluble) {
|
||||
// safeOffsetInc can only work in steps of the size xy_min_distance in the worst case => xy_min_distance has to be a bit larger than 0 in this worst case and should be large enough for performance to not suffer extremely
|
||||
// When for all meshes the z bottom and top distance is more than one layer though the worst case is xy_min_distance + min_feature_size
|
||||
// This is not the best solution, but the only one to ensure areas can not lag though walls at high maximum_move_distance.
|
||||
xy_min_distance = std::max(xy_min_distance, scaled<coord_t>(0.1));
|
||||
xy_distance = std::max(xy_distance, xy_min_distance);
|
||||
}
|
||||
|
||||
|
||||
// const std::unordered_map<std::string, InterfacePreference> interface_map = { { "support_area_overwrite_interface_area", InterfacePreference::SupportAreaOverwritesInterface }, { "interface_area_overwrite_support_area", InterfacePreference::InterfaceAreaOverwritesSupport }, { "support_lines_overwrite_interface_area", InterfacePreference::SupportLinesOverwriteInterface }, { "interface_lines_overwrite_support_area", InterfacePreference::InterfaceLinesOverwriteSupport }, { "nothing", InterfacePreference::Nothing } };
|
||||
// interface_preference = interface_map.at(mesh_group_settings.get<std::string>("support_interface_priority"));
|
||||
//FIXME this was the default
|
||||
// interface_preference = InterfacePreference::SupportLinesOverwriteInterface;
|
||||
//interface_preference = InterfacePreference::SupportAreaOverwritesInterface;
|
||||
interface_preference = InterfacePreference::InterfaceAreaOverwritesSupport;
|
||||
|
||||
if (slicing_params.raft_layers() > 0) {
|
||||
// Fill in raft_layers with the heights of the layers below the first object layer.
|
||||
double z = slicing_params.first_print_layer_height;
|
||||
this->raft_layers.emplace_back(z);
|
||||
for (size_t i = 1; i < slicing_params.base_raft_layers; ++ i) {
|
||||
z += slicing_params.base_raft_layer_height;
|
||||
this->raft_layers.emplace_back(z);
|
||||
}
|
||||
for (size_t i = 0; i + 1 < slicing_params.interface_raft_layers; ++ i) {
|
||||
z += slicing_params.interface_raft_layer_height;
|
||||
this->raft_layers.emplace_back(z);
|
||||
}
|
||||
assert(is_approx(z, slicing_params.raft_interface_top_z));
|
||||
double dist_to_go = slicing_params.object_print_z_min - z;
|
||||
assert(dist_to_go > slicing_params.min_layer_height - EPSILON);
|
||||
auto nsteps = int(ceil(dist_to_go / slicing_params.max_suport_layer_height));
|
||||
double step = dist_to_go / nsteps;
|
||||
for (size_t i = 0; i < nsteps; ++ i) {
|
||||
z += step;
|
||||
this->raft_layers.emplace_back(z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class LineStatus
|
||||
{
|
||||
INVALID,
|
||||
@ -158,7 +237,7 @@ static std::vector<std::pair<TreeSupportSettings, std::vector<size_t>>> group_me
|
||||
assert(object_config.support_material_style == smsTree || object_config.support_material_style == smsOrganic);
|
||||
|
||||
bool found_existing_group = false;
|
||||
TreeSupportSettings next_settings{ TreeSupportMeshGroupSettings{ print_object } };
|
||||
TreeSupportSettings next_settings{ TreeSupportMeshGroupSettings{ print_object }, print_object.slicing_parameters() };
|
||||
//FIXME for now only a single object per group is enabled.
|
||||
#if 0
|
||||
for (size_t idx = 0; idx < grouped_meshes.size(); ++ idx)
|
||||
@ -222,9 +301,12 @@ void tree_supports_show_error(std::string_view message, bool critical)
|
||||
#endif // TREE_SUPPORT_SHOW_ERRORS_WIN32
|
||||
}
|
||||
|
||||
[[nodiscard]] static const std::vector<Polygons> generate_overhangs(const PrintObject &print_object, std::function<void()> throw_on_cancel)
|
||||
[[nodiscard]] static const std::vector<Polygons> generate_overhangs(const TreeSupportSettings &settings, const PrintObject &print_object, std::function<void()> throw_on_cancel)
|
||||
{
|
||||
std::vector<Polygons> out(print_object.layer_count(), Polygons{});
|
||||
const size_t num_raft_layers = settings.raft_layers.size();
|
||||
const size_t num_object_layers = print_object.layer_count();
|
||||
const size_t num_layers = num_object_layers + num_raft_layers;
|
||||
std::vector<Polygons> out(num_layers, Polygons{});
|
||||
|
||||
const PrintConfig &print_config = print_object.print()->config();
|
||||
const PrintObjectConfig &config = print_object.config();
|
||||
@ -241,10 +323,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);
|
||||
|
||||
size_t num_overhang_layers = support_auto ? out.size() : std::max(size_t(support_enforce_layers), enforcers_layers.size());
|
||||
size_t num_overhang_layers = support_auto ? num_object_layers : 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]
|
||||
support_auto, support_enforce_layers, support_threshold_auto, tan_threshold, enforcer_overhang_offset, num_raft_layers, &throw_on_cancel, &out]
|
||||
(const tbb::blocked_range<LayerIndex> &range) {
|
||||
for (LayerIndex layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
|
||||
const Layer ¤t_layer = *print_object.get_layer(layer_id);
|
||||
@ -314,11 +396,34 @@ void tree_supports_show_error(std::string_view message, bool critical)
|
||||
//check_self_intersections(overhangs, "generate_overhangs - enforcers");
|
||||
}
|
||||
}
|
||||
out[layer_id] = std::move(overhangs);
|
||||
out[layer_id + num_raft_layers] = std::move(overhangs);
|
||||
throw_on_cancel();
|
||||
}
|
||||
});
|
||||
|
||||
if (num_raft_layers > 0) {
|
||||
const Layer &first_layer = *print_object.get_layer(0);
|
||||
// Final overhangs.
|
||||
Polygons overhangs =
|
||||
// Don't apply blockes on raft layer.
|
||||
//(! blockers_layers.empty() && ! blockers_layers[layer_id].empty() ?
|
||||
// diff(first_layer.lslices, blockers_layers[layer_id], ApplySafetyOffset::Yes) :
|
||||
to_polygons(first_layer.lslices);
|
||||
#if 0
|
||||
if (! enforcers_layers.empty() && ! enforcers_layers[layer_id].empty()) {
|
||||
if (Polygons enforced_overhangs = intersection(first_layer.lslices, enforcers_layers[layer_id] /*, ApplySafetyOffset::Yes */);
|
||||
! enforced_overhangs.empty()) {
|
||||
//FIXME this is a hack to make enforcers work on steep overhangs.
|
||||
//FIXME enforcer_overhang_offset is a fudge constant!
|
||||
enforced_overhangs = offset(union_ex(enforced_overhangs), enforcer_overhang_offset);
|
||||
overhangs = overhangs.empty() ? std::move(enforced_overhangs) : union_(overhangs, enforced_overhangs);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
out[num_raft_layers] = std::move(overhangs);
|
||||
throw_on_cancel();
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
@ -333,16 +438,18 @@ void tree_supports_show_error(std::string_view message, bool critical)
|
||||
// calculate top most layer that is relevant for support
|
||||
LayerIndex max_layer = 0;
|
||||
for (size_t object_id : object_ids) {
|
||||
const PrintObject &print_object = *print.get_object(object_id);
|
||||
int max_support_layer_id = 0;
|
||||
for (int layer_id = 1; layer_id < int(print_object.layer_count()); ++ layer_id)
|
||||
const PrintObject &print_object = *print.get_object(object_id);
|
||||
const int num_raft_layers = int(config.raft_layers.size());
|
||||
const int num_layers = int(print_object.layer_count()) + num_raft_layers;
|
||||
int max_support_layer_id = 0;
|
||||
for (int layer_id = std::max<int>(num_raft_layers, 1); layer_id < num_layers; ++ layer_id)
|
||||
if (! overhangs[layer_id].empty())
|
||||
max_support_layer_id = layer_id;
|
||||
max_layer = std::max(max_support_layer_id - int(config.z_distance_top_layers), 0);
|
||||
}
|
||||
if (max_layer > 0)
|
||||
// The actual precalculation happens in TreeModelVolumes.
|
||||
volumes.precalculate(max_layer, throw_on_cancel);
|
||||
volumes.precalculate(*print.get_object(object_ids.front()), max_layer, throw_on_cancel);
|
||||
return max_layer;
|
||||
}
|
||||
|
||||
@ -815,29 +922,38 @@ static std::optional<std::pair<Point, size_t>> polyline_sample_next_point_at_dis
|
||||
return union_(ret);
|
||||
}
|
||||
|
||||
static double layer_z(const SlicingParameters &slicing_params, const size_t layer_idx)
|
||||
static double layer_z(const SlicingParameters &slicing_params, const TreeSupportSettings &config, const size_t layer_idx)
|
||||
{
|
||||
return slicing_params.object_print_z_min + slicing_params.first_object_layer_height + layer_idx * slicing_params.layer_height;
|
||||
return layer_idx >= config.raft_layers.size() ?
|
||||
slicing_params.object_print_z_min + slicing_params.first_object_layer_height + (layer_idx - config.raft_layers.size()) * slicing_params.layer_height :
|
||||
config.raft_layers[layer_idx];
|
||||
}
|
||||
static LayerIndex layer_idx_ceil(const SlicingParameters &slicing_params, const double z)
|
||||
// Lowest collision layer
|
||||
static LayerIndex layer_idx_ceil(const SlicingParameters &slicing_params, const TreeSupportSettings &config, const double z)
|
||||
{
|
||||
return LayerIndex(ceil((z - slicing_params.object_print_z_min - slicing_params.first_object_layer_height) / slicing_params.layer_height));
|
||||
return
|
||||
LayerIndex(config.raft_layers.size()) +
|
||||
std::max<LayerIndex>(0, ceil((z - slicing_params.object_print_z_min - slicing_params.first_object_layer_height) / slicing_params.layer_height));
|
||||
}
|
||||
static LayerIndex layer_idx_floor(const SlicingParameters &slicing_params, const double z)
|
||||
// Highest collision layer
|
||||
static LayerIndex layer_idx_floor(const SlicingParameters &slicing_params, const TreeSupportSettings &config, const double z)
|
||||
{
|
||||
return LayerIndex(floor((z - slicing_params.object_print_z_min - slicing_params.first_object_layer_height) / slicing_params.layer_height));
|
||||
return
|
||||
LayerIndex(config.raft_layers.size()) +
|
||||
std::max<LayerIndex>(0, floor((z - slicing_params.object_print_z_min - slicing_params.first_object_layer_height) / slicing_params.layer_height));
|
||||
}
|
||||
|
||||
static inline SupportGeneratorLayer& layer_initialize(
|
||||
SupportGeneratorLayer &layer_new,
|
||||
const SupporLayerType layer_type,
|
||||
const SlicingParameters &slicing_params,
|
||||
const TreeSupportSettings &config,
|
||||
const size_t layer_idx)
|
||||
{
|
||||
layer_new.layer_type = layer_type;
|
||||
layer_new.print_z = layer_z(slicing_params, layer_idx);
|
||||
layer_new.height = layer_idx == 0 ? slicing_params.first_object_layer_height : slicing_params.layer_height;
|
||||
layer_new.bottom_z = layer_idx == 0 ? slicing_params.object_print_z_min : layer_new.print_z - layer_new.height;
|
||||
layer_new.print_z = layer_z(slicing_params, config, layer_idx);
|
||||
layer_new.bottom_z = layer_idx > 0 ? layer_z(slicing_params, config, layer_idx - 1) : 0;
|
||||
layer_new.height = layer_new.print_z - layer_new.bottom_z;
|
||||
return layer_new;
|
||||
}
|
||||
|
||||
@ -846,11 +962,12 @@ inline SupportGeneratorLayer& layer_allocate(
|
||||
std::deque<SupportGeneratorLayer> &layer_storage,
|
||||
SupporLayerType layer_type,
|
||||
const SlicingParameters &slicing_params,
|
||||
const TreeSupportSettings &config,
|
||||
size_t layer_idx)
|
||||
{
|
||||
//FIXME take raft into account.
|
||||
layer_storage.push_back(SupportGeneratorLayer());
|
||||
return layer_initialize(layer_storage.back(), layer_type, slicing_params, layer_idx);
|
||||
return layer_initialize(layer_storage.back(), layer_type, slicing_params, config, layer_idx);
|
||||
}
|
||||
|
||||
inline SupportGeneratorLayer& layer_allocate(
|
||||
@ -858,11 +975,12 @@ inline SupportGeneratorLayer& layer_allocate(
|
||||
tbb::spin_mutex& layer_storage_mutex,
|
||||
SupporLayerType layer_type,
|
||||
const SlicingParameters &slicing_params,
|
||||
const TreeSupportSettings &config,
|
||||
size_t layer_idx)
|
||||
{
|
||||
tbb::spin_mutex::scoped_lock lock(layer_storage_mutex);
|
||||
layer_storage.push_back(SupportGeneratorLayer());
|
||||
return layer_initialize(layer_storage.back(), layer_type, slicing_params, layer_idx);
|
||||
return layer_initialize(layer_storage.back(), layer_type, slicing_params, config, layer_idx);
|
||||
}
|
||||
|
||||
using SupportElements = std::deque<SupportElement>;
|
||||
@ -890,7 +1008,7 @@ static void generate_initial_areas(
|
||||
static constexpr const auto base_radius = scaled<int>(0.01);
|
||||
const Polygon base_circle = make_circle(base_radius, SUPPORT_TREE_CIRCLE_RESOLUTION);
|
||||
TreeSupportMeshGroupSettings mesh_group_settings(print_object);
|
||||
TreeSupportSettings mesh_config{ mesh_group_settings };
|
||||
TreeSupportSettings mesh_config{ mesh_group_settings, print_object.slicing_parameters() };
|
||||
SupportParameters support_params(print_object);
|
||||
support_params.with_sheath = true;
|
||||
support_params.support_density = 0;
|
||||
@ -936,11 +1054,13 @@ static void generate_initial_areas(
|
||||
0;
|
||||
|
||||
//FIXME
|
||||
size_t num_support_layers = print_object.layer_count();
|
||||
std::vector<std::unordered_set<Point, PointHash>> already_inserted(num_support_layers - z_distance_delta);
|
||||
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 first_support_layer = std::max(int(num_raft_layers) - int(z_distance_delta), 1);
|
||||
std::vector<std::unordered_set<Point, PointHash>> already_inserted(num_support_layers);
|
||||
|
||||
std::mutex mutex_layer_storage, mutex_movebounds;
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(1, num_support_layers - z_distance_delta),
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(first_support_layer, num_support_layers),
|
||||
[&print_object, &volumes, &config, &overhangs, &mesh_config, &mesh_group_settings, &support_params,
|
||||
z_distance_delta, min_xy_dist, 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, &mutex_layer_storage, &mutex_movebounds, &top_contacts, &layer_storage, &already_inserted,
|
||||
@ -1060,7 +1180,7 @@ static void generate_initial_areas(
|
||||
std::lock_guard<std::mutex> lock(mutex_layer_storage);
|
||||
SupportGeneratorLayer *&l = top_contacts[insert_layer_idx - dtt_roof_tip];
|
||||
if (l == nullptr)
|
||||
l = &layer_allocate(layer_storage, SupporLayerType::TopContact, print_object.slicing_parameters(), insert_layer_idx - dtt_roof_tip);
|
||||
l = &layer_allocate(layer_storage, SupporLayerType::TopContact, print_object.slicing_parameters(), config, insert_layer_idx - dtt_roof_tip);
|
||||
append(l->polygons, std::move(added_roofs));
|
||||
}
|
||||
}
|
||||
@ -1242,7 +1362,7 @@ static void generate_initial_areas(
|
||||
if (! added_roofs[idx].empty()) {
|
||||
SupportGeneratorLayer *&l = top_contacts[layer_idx - idx];
|
||||
if (l == nullptr)
|
||||
l = &layer_allocate(layer_storage, SupporLayerType::TopContact, print_object.slicing_parameters(), layer_idx - idx);
|
||||
l = &layer_allocate(layer_storage, SupporLayerType::TopContact, print_object.slicing_parameters(), config, layer_idx - idx);
|
||||
// will be unioned in finalize_interface_and_support_areas()
|
||||
append(l->polygons, std::move(added_roofs[idx]));
|
||||
}
|
||||
@ -1280,7 +1400,7 @@ static void generate_initial_areas(
|
||||
std::lock_guard<std::mutex> lock(mutex_layer_storage);
|
||||
SupportGeneratorLayer*& l = top_contacts[0];
|
||||
if (l == nullptr)
|
||||
l = &layer_allocate(layer_storage, SupporLayerType::TopContact, print_object.slicing_parameters(), 0);
|
||||
l = &layer_allocate(layer_storage, SupporLayerType::TopContact, print_object.slicing_parameters(), config, 0);
|
||||
append(l->polygons, std::move(overhang_outset));
|
||||
} 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);
|
||||
@ -3047,7 +3167,7 @@ static void finalize_interface_and_support_areas(
|
||||
}
|
||||
if (! floor_layer.empty()) {
|
||||
if (support_bottom == nullptr)
|
||||
support_bottom = &layer_allocate(layer_storage, layer_storage_mutex, SupporLayerType::BottomContact, print_object.slicing_parameters(), layer_idx);
|
||||
support_bottom = &layer_allocate(layer_storage, layer_storage_mutex, SupporLayerType::BottomContact, print_object.slicing_parameters(), config, layer_idx);
|
||||
support_bottom->polygons = union_(floor_layer, support_bottom->polygons);
|
||||
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.
|
||||
}
|
||||
@ -3055,11 +3175,11 @@ static void finalize_interface_and_support_areas(
|
||||
|
||||
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 = top_contacts[layer_idx] = &layer_allocate(layer_storage, layer_storage_mutex, SupporLayerType::TopContact, print_object.slicing_parameters(), config, 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);
|
||||
SupportGeneratorLayer *base_layer = intermediate_layers[layer_idx] = &layer_allocate(layer_storage, layer_storage_mutex, SupporLayerType::Base, print_object.slicing_parameters(), config, layer_idx);
|
||||
base_layer->polygons = union_(base_layer_polygons);
|
||||
}
|
||||
|
||||
@ -3391,8 +3511,8 @@ static void extrude_branch(
|
||||
const SupportElement &prev = *path[ipath - 1];
|
||||
const SupportElement ¤t = *path[ipath];
|
||||
assert(prev.state.layer_idx + 1 == current.state.layer_idx);
|
||||
p1 = to_3d(unscaled<double>(prev .state.result_on_layer), layer_z(slicing_params, prev .state.layer_idx));
|
||||
p2 = to_3d(unscaled<double>(current.state.result_on_layer), layer_z(slicing_params, current.state.layer_idx));
|
||||
p1 = to_3d(unscaled<double>(prev .state.result_on_layer), layer_z(slicing_params, config, prev .state.layer_idx));
|
||||
p2 = to_3d(unscaled<double>(current.state.result_on_layer), layer_z(slicing_params, config, current.state.layer_idx));
|
||||
v1 = (p2 - p1).normalized();
|
||||
if (ipath == 1) {
|
||||
nprev = v1;
|
||||
@ -3439,7 +3559,7 @@ static void extrude_branch(
|
||||
} else {
|
||||
const SupportElement &next = *path[ipath + 1];
|
||||
assert(current.state.layer_idx + 1 == next.state.layer_idx);
|
||||
p3 = to_3d(unscaled<double>(next.state.result_on_layer), layer_z(slicing_params, next.state.layer_idx));
|
||||
p3 = to_3d(unscaled<double>(next.state.result_on_layer), layer_z(slicing_params, config, next.state.layer_idx));
|
||||
v2 = (p3 - p2).normalized();
|
||||
ncurrent = (v1 + v2).normalized();
|
||||
float radius = unscaled<float>(config.getRadius(current.state));
|
||||
@ -3549,7 +3669,7 @@ static void organic_smooth_branches_avoid_collisions(
|
||||
element.parents.empty() || (link_down == -1 && element.state.layer_idx > 0),
|
||||
unscaled<float>(config.getRadius(element.state)),
|
||||
// 3D position
|
||||
to_3d(unscaled<float>(element.state.result_on_layer), float(layer_z(slicing_params, element.state.layer_idx)))
|
||||
to_3d(unscaled<float>(element.state.result_on_layer), float(layer_z(slicing_params, config, element.state.layer_idx)))
|
||||
});
|
||||
// Update min_z coordinate to min_z of the tree below.
|
||||
CollisionSphere &collision_sphere = collision_spheres.back();
|
||||
@ -3580,8 +3700,9 @@ static void organic_smooth_branches_avoid_collisions(
|
||||
//FIXME limit the collision span by the tree slope.
|
||||
collision_sphere.min_z = std::max(collision_sphere.min_z, collision_sphere.position.z() - collision_sphere.radius);
|
||||
collision_sphere.max_z = std::min(collision_sphere.max_z, collision_sphere.position.z() + collision_sphere.radius);
|
||||
collision_sphere.layer_begin = std::min(collision_sphere.element.state.layer_idx, layer_idx_ceil(slicing_params, collision_sphere.min_z));
|
||||
collision_sphere.layer_end = std::max(collision_sphere.element.state.layer_idx, layer_idx_floor(slicing_params, collision_sphere.max_z)) + 1;
|
||||
collision_sphere.layer_begin = std::min(collision_sphere.element.state.layer_idx, layer_idx_ceil(slicing_params, config, collision_sphere.min_z));
|
||||
assert(collision_sphere.layer_begin < layer_collision_cache.size());
|
||||
collision_sphere.layer_end = std::min(LayerIndex(layer_collision_cache.size()), std::max(collision_sphere.element.state.layer_idx, layer_idx_floor(slicing_params, config, collision_sphere.max_z)) + 1);
|
||||
}
|
||||
|
||||
throw_on_cancel();
|
||||
@ -3596,7 +3717,7 @@ static void organic_smooth_branches_avoid_collisions(
|
||||
collision_sphere.prev_position = collision_sphere.position;
|
||||
std::atomic<size_t> num_moved{ 0 };
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, collision_spheres.size()),
|
||||
[&collision_spheres, &layer_collision_cache, &slicing_params, &move_bounds, &linear_data_layers, &num_moved, &throw_on_cancel](const tbb::blocked_range<size_t> range) {
|
||||
[&collision_spheres, &layer_collision_cache, &slicing_params, &config, &move_bounds, &linear_data_layers, &num_moved, &throw_on_cancel](const tbb::blocked_range<size_t> range) {
|
||||
for (size_t collision_sphere_id = range.begin(); collision_sphere_id < range.end(); ++ collision_sphere_id)
|
||||
if (CollisionSphere &collision_sphere = collision_spheres[collision_sphere_id]; ! collision_sphere.locked) {
|
||||
// Calculate collision of multiple 2D layers against a collision sphere.
|
||||
@ -3613,7 +3734,7 @@ static void organic_smooth_branches_avoid_collisions(
|
||||
double collision_depth = sqrt(r2) - dist;
|
||||
if (collision_depth > collision_sphere.last_collision_depth) {
|
||||
collision_sphere.last_collision_depth = collision_depth;
|
||||
collision_sphere.last_collision = to_3d(hit_point_out.cast<float>(), float(layer_z(slicing_params, layer_id)));
|
||||
collision_sphere.last_collision = to_3d(hit_point_out.cast<float>(), float(layer_z(slicing_params, config, layer_id)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3693,7 +3814,7 @@ static void organic_smooth_branches_avoid_collisions(
|
||||
std::vector<openvdb::Vec3R> pts, prev, projections;
|
||||
std::vector<float> distances;
|
||||
for (const std::pair<SupportElement*, int>& element : elements_with_link_down) {
|
||||
Vec3d pt = to_3d(unscaled<double>(element.first->state.result_on_layer), layer_z(print_object.slicing_parameters(), element.first->state.layer_idx)) * scale;
|
||||
Vec3d pt = to_3d(unscaled<double>(element.first->state.result_on_layer), layer_z(print_object.slicing_parameters(), config, element.first->state.layer_idx)) * scale;
|
||||
pts.push_back({ pt.x(), pt.y(), pt.z() });
|
||||
}
|
||||
|
||||
@ -3918,9 +4039,9 @@ static void slice_branches(
|
||||
const SlicingParameters &slicing_params = print_object.slicing_parameters();
|
||||
std::vector<float> slice_z;
|
||||
for (size_t layer_idx = 0; layer_idx < move_bounds.size(); ++ layer_idx) {
|
||||
double print_z = slicing_params.object_print_z_min + slicing_params.first_object_layer_height + layer_idx * slicing_params.layer_height;
|
||||
double layer_height = layer_idx == 0 ? slicing_params.first_object_layer_height : slicing_params.layer_height;
|
||||
slice_z.emplace_back(float(print_z - layer_height * 0.5));
|
||||
const double print_z = layer_z(print_object.slicing_parameters(), config, layer_idx);
|
||||
const double bottom_z = layer_idx > 0 ? layer_z(print_object.slicing_parameters(), config, layer_idx - 1) : 0.;
|
||||
slice_z.emplace_back(float(0.5 * (bottom_z + print_z)));
|
||||
}
|
||||
// Remove the trailing slices.
|
||||
while (! slice_z.empty())
|
||||
@ -4009,7 +4130,7 @@ static void generate_support_areas(Print &print, const BuildVolume &build_volume
|
||||
|
||||
//FIXME generating overhangs just for the furst mesh of the group.
|
||||
assert(processing.second.size() == 1);
|
||||
std::vector<Polygons> overhangs = generate_overhangs(*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.
|
||||
size_t num_support_layers = precalculate(print, overhangs, processing.first, processing.second, volumes, throw_on_cancel);
|
||||
|
@ -40,6 +40,7 @@ namespace Slic3r
|
||||
class Print;
|
||||
class PrintObject;
|
||||
class SupportGeneratorLayer;
|
||||
struct SlicingParameters;
|
||||
using SupportGeneratorLayerStorage = std::deque<SupportGeneratorLayer>;
|
||||
using SupportGeneratorLayersPtr = std::vector<SupportGeneratorLayer*>;
|
||||
|
||||
@ -255,64 +256,7 @@ struct SupportElement
|
||||
struct TreeSupportSettings
|
||||
{
|
||||
TreeSupportSettings() = default; // required for the definition of the config variable in the TreeSupportGenerator class.
|
||||
|
||||
explicit TreeSupportSettings(const TreeSupportMeshGroupSettings& mesh_group_settings)
|
||||
: angle(mesh_group_settings.support_tree_angle),
|
||||
angle_slow(mesh_group_settings.support_tree_angle_slow),
|
||||
support_line_width(mesh_group_settings.support_line_width),
|
||||
layer_height(mesh_group_settings.layer_height),
|
||||
branch_radius(mesh_group_settings.support_tree_branch_diameter / 2),
|
||||
min_radius(mesh_group_settings.support_tree_tip_diameter / 2), // The actual radius is 50 microns larger as the resulting branches will be increased by 50 microns to avoid rounding errors effectively increasing the xydistance
|
||||
maximum_move_distance((angle < M_PI / 2.) ? (coord_t)(tan(angle) * layer_height) : std::numeric_limits<coord_t>::max()),
|
||||
maximum_move_distance_slow((angle_slow < M_PI / 2.) ? (coord_t)(tan(angle_slow) * layer_height) : std::numeric_limits<coord_t>::max()),
|
||||
support_bottom_layers(mesh_group_settings.support_bottom_enable ? (mesh_group_settings.support_bottom_height + layer_height / 2) / layer_height : 0),
|
||||
tip_layers(std::max((branch_radius - min_radius) / (support_line_width / 3), branch_radius / layer_height)), // Ensure lines always stack nicely even if layer height is large
|
||||
diameter_angle_scale_factor(sin(mesh_group_settings.support_tree_branch_diameter_angle) * layer_height / branch_radius),
|
||||
max_to_model_radius_increase(mesh_group_settings.support_tree_max_diameter_increase_by_merges_when_support_to_model / 2),
|
||||
min_dtt_to_model(round_up_divide(mesh_group_settings.support_tree_min_height_to_model, layer_height)),
|
||||
increase_radius_until_radius(mesh_group_settings.support_tree_branch_diameter / 2),
|
||||
increase_radius_until_layer(increase_radius_until_radius <= branch_radius ? tip_layers * (increase_radius_until_radius / branch_radius) : (increase_radius_until_radius - branch_radius) / (branch_radius * diameter_angle_scale_factor)),
|
||||
support_rests_on_model(! mesh_group_settings.support_material_buildplate_only),
|
||||
xy_distance(mesh_group_settings.support_xy_distance),
|
||||
xy_min_distance(std::min(mesh_group_settings.support_xy_distance, mesh_group_settings.support_xy_distance_overhang)),
|
||||
bp_radius(mesh_group_settings.support_tree_bp_diameter / 2),
|
||||
diameter_scale_bp_radius(std::min(sin(0.7) * layer_height / branch_radius, 1.0 / (branch_radius / (support_line_width / 2.0)))), // Either 40? or as much as possible so that 2 lines will overlap by at least 50%, whichever is smaller.
|
||||
z_distance_top_layers(round_up_divide(mesh_group_settings.support_top_distance, layer_height)),
|
||||
z_distance_bottom_layers(round_up_divide(mesh_group_settings.support_bottom_distance, layer_height)),
|
||||
performance_interface_skip_layers(round_up_divide(mesh_group_settings.support_interface_skip_height, layer_height)),
|
||||
// support_infill_angles(mesh_group_settings.support_infill_angles),
|
||||
support_roof_angles(mesh_group_settings.support_roof_angles),
|
||||
roof_pattern(mesh_group_settings.support_roof_pattern),
|
||||
support_pattern(mesh_group_settings.support_pattern),
|
||||
support_roof_line_width(mesh_group_settings.support_roof_line_width),
|
||||
support_line_spacing(mesh_group_settings.support_line_spacing),
|
||||
support_bottom_offset(mesh_group_settings.support_bottom_offset),
|
||||
support_wall_count(mesh_group_settings.support_wall_count),
|
||||
resolution(mesh_group_settings.resolution),
|
||||
support_roof_line_distance(mesh_group_settings.support_roof_line_distance), // in the end the actual infill has to be calculated to subtract interface from support areas according to interface_preference.
|
||||
settings(mesh_group_settings),
|
||||
min_feature_size(mesh_group_settings.min_feature_size)
|
||||
|
||||
|
||||
{
|
||||
layer_start_bp_radius = (bp_radius - branch_radius) / (branch_radius * diameter_scale_bp_radius);
|
||||
|
||||
if (TreeSupportSettings::soluble) {
|
||||
// safeOffsetInc can only work in steps of the size xy_min_distance in the worst case => xy_min_distance has to be a bit larger than 0 in this worst case and should be large enough for performance to not suffer extremely
|
||||
// When for all meshes the z bottom and top distance is more than one layer though the worst case is xy_min_distance + min_feature_size
|
||||
// This is not the best solution, but the only one to ensure areas can not lag though walls at high maximum_move_distance.
|
||||
xy_min_distance = std::max(xy_min_distance, scaled<coord_t>(0.1));
|
||||
xy_distance = std::max(xy_distance, xy_min_distance);
|
||||
}
|
||||
|
||||
|
||||
// const std::unordered_map<std::string, InterfacePreference> interface_map = { { "support_area_overwrite_interface_area", InterfacePreference::SupportAreaOverwritesInterface }, { "interface_area_overwrite_support_area", InterfacePreference::InterfaceAreaOverwritesSupport }, { "support_lines_overwrite_interface_area", InterfacePreference::SupportLinesOverwriteInterface }, { "interface_lines_overwrite_support_area", InterfacePreference::InterfaceLinesOverwriteSupport }, { "nothing", InterfacePreference::Nothing } };
|
||||
// interface_preference = interface_map.at(mesh_group_settings.get<std::string>("support_interface_priority"));
|
||||
//FIXME this was the default
|
||||
// interface_preference = InterfacePreference::SupportLinesOverwriteInterface;
|
||||
//interface_preference = InterfacePreference::SupportAreaOverwritesInterface;
|
||||
interface_preference = InterfacePreference::InterfaceAreaOverwritesSupport;
|
||||
}
|
||||
explicit TreeSupportSettings(const TreeSupportMeshGroupSettings &mesh_group_settings, const SlicingParameters &slicing_params);
|
||||
|
||||
private:
|
||||
double angle;
|
||||
@ -466,6 +410,9 @@ public:
|
||||
*/
|
||||
coord_t min_feature_size;
|
||||
|
||||
// Extra raft layers below the object.
|
||||
std::vector<coordf_t> raft_layers;
|
||||
|
||||
public:
|
||||
bool operator==(const TreeSupportSettings& other) const
|
||||
{
|
||||
@ -497,6 +444,7 @@ public:
|
||||
settings.get<int>("meshfix_maximum_extrusion_area_deviation") == other.settings.get<int>("meshfix_maximum_extrusion_area_deviation"))
|
||||
)
|
||||
#endif
|
||||
&& raft_layers == other.raft_layers
|
||||
;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user