mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-08 07:27:41 -06:00
FIX: support wall count doesn't work
jira: STUDIO-7975 Change-Id: Ic580d298568fc6eab8b1a2c017fa182869b432bf (cherry picked from commit 82bcb099e139065cc00c133f507e955d9955b2f4) (cherry picked from commit 04756bf447f690a071eace1500b150f0b7b4ce02)
This commit is contained in:
parent
ae6fadda4d
commit
f76683e90e
6 changed files with 95 additions and 84 deletions
|
@ -4955,10 +4955,11 @@ void PrintConfigDef::init_fff_params()
|
||||||
def = this->add("tree_support_wall_count", coInt);
|
def = this->add("tree_support_wall_count", coInt);
|
||||||
def->label = L("Support wall loops");
|
def->label = L("Support wall loops");
|
||||||
def->category = L("Support");
|
def->category = L("Support");
|
||||||
def->tooltip = L("This setting specify the count of walls around support");
|
def->tooltip = L("This setting specifies the min count of support walls in the range of [0,2]. Actual wall count may be larger than the specified value.");
|
||||||
def->min = 0;
|
def->min = 0;
|
||||||
|
def->max = 2;
|
||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionInt(0));
|
def->set_default_value(new ConfigOptionInt(1));
|
||||||
|
|
||||||
def = this->add("tree_support_with_infill", coBool);
|
def = this->add("tree_support_with_infill", coBool);
|
||||||
def->label = L("Tree support with infill");
|
def->label = L("Tree support with infill");
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace Slic3r {
|
||||||
|
|
||||||
// how much we extend support around the actual contact area
|
// how much we extend support around the actual contact area
|
||||||
//FIXME this should be dependent on the nozzle diameter!
|
//FIXME this should be dependent on the nozzle diameter!
|
||||||
#define SUPPORT_MATERIAL_MARGIN 1.5
|
#define SUPPORT_MATERIAL_MARGIN 1.5
|
||||||
|
|
||||||
//#define SUPPORT_SURFACES_OFFSET_PARAMETERS ClipperLib::jtMiter, 3.
|
//#define SUPPORT_SURFACES_OFFSET_PARAMETERS ClipperLib::jtMiter, 3.
|
||||||
//#define SUPPORT_SURFACES_OFFSET_PARAMETERS ClipperLib::jtMiter, 1.5
|
//#define SUPPORT_SURFACES_OFFSET_PARAMETERS ClipperLib::jtMiter, 1.5
|
||||||
|
@ -144,6 +144,7 @@ std::pair<SupportGeneratorLayersPtr, SupportGeneratorLayersPtr> generate_interfa
|
||||||
const bool smooth_supports = support_params.support_style != smsGrid;
|
const bool smooth_supports = support_params.support_style != smsGrid;
|
||||||
SupportGeneratorLayersPtr &interface_layers = base_and_interface_layers.first;
|
SupportGeneratorLayersPtr &interface_layers = base_and_interface_layers.first;
|
||||||
SupportGeneratorLayersPtr &base_interface_layers = base_and_interface_layers.second;
|
SupportGeneratorLayersPtr &base_interface_layers = base_and_interface_layers.second;
|
||||||
|
|
||||||
interface_layers.assign(intermediate_layers.size(), nullptr);
|
interface_layers.assign(intermediate_layers.size(), nullptr);
|
||||||
if (support_params.has_base_interfaces())
|
if (support_params.has_base_interfaces())
|
||||||
base_interface_layers.assign(intermediate_layers.size(), nullptr);
|
base_interface_layers.assign(intermediate_layers.size(), nullptr);
|
||||||
|
@ -152,7 +153,7 @@ std::pair<SupportGeneratorLayersPtr, SupportGeneratorLayersPtr> generate_interfa
|
||||||
const auto closing_distance = smoothing_distance; // scaled<float>(config.support_material_closing_radius.value);
|
const auto closing_distance = smoothing_distance; // scaled<float>(config.support_material_closing_radius.value);
|
||||||
// Insert a new layer into base_interface_layers, if intersection with base exists.
|
// Insert a new layer into base_interface_layers, if intersection with base exists.
|
||||||
auto insert_layer = [&layer_storage, smooth_supports, closing_distance, smoothing_distance, minimum_island_radius](
|
auto insert_layer = [&layer_storage, smooth_supports, closing_distance, smoothing_distance, minimum_island_radius](
|
||||||
SupportGeneratorLayer &intermediate_layer, Polygons &bottom, Polygons &&top, SupportGeneratorLayer *top_interface_layer,
|
SupportGeneratorLayer &intermediate_layer, Polygons &bottom, Polygons &&top, SupportGeneratorLayer *top_interface_layer,
|
||||||
const Polygons *subtract, SupporLayerType type) -> SupportGeneratorLayer* {
|
const Polygons *subtract, SupporLayerType type) -> SupportGeneratorLayer* {
|
||||||
bool has_top_interface = top_interface_layer && ! top_interface_layer->polygons.empty();
|
bool has_top_interface = top_interface_layer && ! top_interface_layer->polygons.empty();
|
||||||
assert(! bottom.empty() || ! top.empty() || has_top_interface);
|
assert(! bottom.empty() || ! top.empty() || has_top_interface);
|
||||||
|
@ -194,7 +195,7 @@ std::pair<SupportGeneratorLayersPtr, SupportGeneratorLayersPtr> generate_interfa
|
||||||
};
|
};
|
||||||
tbb::parallel_for(tbb::blocked_range<int>(0, int(intermediate_layers.size())),
|
tbb::parallel_for(tbb::blocked_range<int>(0, int(intermediate_layers.size())),
|
||||||
[&bottom_contacts, &top_contacts, &top_interface_layers, &top_base_interface_layers, &intermediate_layers, &insert_layer, &support_params,
|
[&bottom_contacts, &top_contacts, &top_interface_layers, &top_base_interface_layers, &intermediate_layers, &insert_layer, &support_params,
|
||||||
snug_supports, &interface_layers, &base_interface_layers](const tbb::blocked_range<int>& range) {
|
snug_supports, &interface_layers, &base_interface_layers](const tbb::blocked_range<int>& range) {
|
||||||
// Gather the top / bottom contact layers intersecting with num_interface_layers resp. num_interface_layers_only intermediate layers above / below
|
// Gather the top / bottom contact layers intersecting with num_interface_layers resp. num_interface_layers_only intermediate layers above / below
|
||||||
// this intermediate layer.
|
// this intermediate layer.
|
||||||
// Index of the first top contact layer intersecting the current intermediate layer.
|
// Index of the first top contact layer intersecting the current intermediate layer.
|
||||||
|
@ -230,7 +231,7 @@ std::pair<SupportGeneratorLayersPtr, SupportGeneratorLayersPtr> generate_interfa
|
||||||
//FIXME maybe this adds one interface layer in excess?
|
//FIXME maybe this adds one interface layer in excess?
|
||||||
if (top_contact_layer.bottom_z - EPSILON > top_z)
|
if (top_contact_layer.bottom_z - EPSILON > top_z)
|
||||||
break;
|
break;
|
||||||
polygons_append(top_contact_layer.bottom_z - EPSILON > top_inteface_z ? polygons_top_contact_projected_base : polygons_top_contact_projected_interface,
|
polygons_append(top_contact_layer.bottom_z - EPSILON > top_inteface_z ? polygons_top_contact_projected_base : polygons_top_contact_projected_interface,
|
||||||
// For snug supports, project the overhang polygons covering the whole overhang, so that they will merge without a gap with support polygons of the other layers.
|
// For snug supports, project the overhang polygons covering the whole overhang, so that they will merge without a gap with support polygons of the other layers.
|
||||||
// For grid supports, merging of support regions will be performed by the projection into grid.
|
// For grid supports, merging of support regions will be performed by the projection into grid.
|
||||||
snug_supports ? *top_contact_layer.overhang_polygons : top_contact_layer.polygons);
|
snug_supports ? *top_contact_layer.overhang_polygons : top_contact_layer.polygons);
|
||||||
|
@ -242,7 +243,7 @@ std::pair<SupportGeneratorLayersPtr, SupportGeneratorLayersPtr> generate_interfa
|
||||||
coordf_t bottom_interface_z = - std::numeric_limits<coordf_t>::max();
|
coordf_t bottom_interface_z = - std::numeric_limits<coordf_t>::max();
|
||||||
if (support_params.num_bottom_base_interface_layers > 0)
|
if (support_params.num_bottom_base_interface_layers > 0)
|
||||||
// Some bottom base interface layers will be generated.
|
// Some bottom base interface layers will be generated.
|
||||||
bottom_interface_z = support_params.num_bottom_interface_layers_only() == 0 ?
|
bottom_interface_z = support_params.num_bottom_interface_layers_only() == 0 ?
|
||||||
// Only base interface layers to generate.
|
// Only base interface layers to generate.
|
||||||
std::numeric_limits<coordf_t>::max() :
|
std::numeric_limits<coordf_t>::max() :
|
||||||
intermediate_layers[std::max(0, idx_intermediate_layer - int(support_params.num_bottom_interface_layers_only()))]->bottom_z;
|
intermediate_layers[std::max(0, idx_intermediate_layer - int(support_params.num_bottom_interface_layers_only()))]->bottom_z;
|
||||||
|
@ -307,7 +308,7 @@ std::pair<SupportGeneratorLayersPtr, SupportGeneratorLayersPtr> generate_interfa
|
||||||
base_interface_layers = merge_remove_empty(base_interface_layers, top_base_interface_layers);
|
base_interface_layers = merge_remove_empty(base_interface_layers, top_base_interface_layers);
|
||||||
BOOST_LOG_TRIVIAL(debug) << "PrintObjectSupportMaterial::generate_interface_layers() in parallel - end";
|
BOOST_LOG_TRIVIAL(debug) << "PrintObjectSupportMaterial::generate_interface_layers() in parallel - end";
|
||||||
}
|
}
|
||||||
|
|
||||||
return base_and_interface_layers;
|
return base_and_interface_layers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -836,8 +837,8 @@ struct SupportGeneratorLayerExtruded
|
||||||
return layer == nullptr || layer->polygons.empty();
|
return layer == nullptr || layer->polygons.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_polygons_to_extrude(Polygons &&polygons) {
|
void set_polygons_to_extrude(Polygons &&polygons) {
|
||||||
if (m_polygons_to_extrude == nullptr)
|
if (m_polygons_to_extrude == nullptr)
|
||||||
m_polygons_to_extrude = std::make_unique<Polygons>(std::move(polygons));
|
m_polygons_to_extrude = std::make_unique<Polygons>(std::move(polygons));
|
||||||
else
|
else
|
||||||
*m_polygons_to_extrude = std::move(polygons);
|
*m_polygons_to_extrude = std::move(polygons);
|
||||||
|
@ -846,9 +847,9 @@ struct SupportGeneratorLayerExtruded
|
||||||
const Polygons& polygons_to_extrude() const { return (m_polygons_to_extrude == nullptr) ? layer->polygons : *m_polygons_to_extrude; }
|
const Polygons& polygons_to_extrude() const { return (m_polygons_to_extrude == nullptr) ? layer->polygons : *m_polygons_to_extrude; }
|
||||||
|
|
||||||
bool could_merge(const SupportGeneratorLayerExtruded &other) const {
|
bool could_merge(const SupportGeneratorLayerExtruded &other) const {
|
||||||
return ! this->empty() && ! other.empty() &&
|
return ! this->empty() && ! other.empty() &&
|
||||||
std::abs(this->layer->height - other.layer->height) < EPSILON &&
|
std::abs(this->layer->height - other.layer->height) < EPSILON &&
|
||||||
this->layer->bridging == other.layer->bridging;
|
this->layer->bridging == other.layer->bridging;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge regions, perform boolean union over the merged polygons.
|
// Merge regions, perform boolean union over the merged polygons.
|
||||||
|
@ -954,7 +955,7 @@ void LoopInterfaceProcessor::generate(SupportGeneratorLayerExtruded &top_contact
|
||||||
const Point* operator()(const Point &pt) const { return &pt; }
|
const Point* operator()(const Point &pt) const { return &pt; }
|
||||||
};
|
};
|
||||||
typedef ClosestPointInRadiusLookup<Point, PointAccessor> ClosestPointLookupType;
|
typedef ClosestPointInRadiusLookup<Point, PointAccessor> ClosestPointLookupType;
|
||||||
|
|
||||||
Polygons loops0;
|
Polygons loops0;
|
||||||
{
|
{
|
||||||
// find centerline of the external loop of the contours
|
// find centerline of the external loop of the contours
|
||||||
|
@ -1051,7 +1052,7 @@ void LoopInterfaceProcessor::generate(SupportGeneratorLayerExtruded &top_contact
|
||||||
for (int i = 1; i < n_contact_loops; ++ i)
|
for (int i = 1; i < n_contact_loops; ++ i)
|
||||||
polygons_append(loop_polygons,
|
polygons_append(loop_polygons,
|
||||||
opening(
|
opening(
|
||||||
loops0,
|
loops0,
|
||||||
i * flow.scaled_spacing() + 0.5f * flow.scaled_spacing(),
|
i * flow.scaled_spacing() + 0.5f * flow.scaled_spacing(),
|
||||||
0.5f * flow.scaled_spacing()));
|
0.5f * flow.scaled_spacing()));
|
||||||
// Clip such loops to the side oriented towards the object.
|
// Clip such loops to the side oriented towards the object.
|
||||||
|
@ -1111,7 +1112,7 @@ void LoopInterfaceProcessor::generate(SupportGeneratorLayerExtruded &top_contact
|
||||||
// Remove empty lines.
|
// Remove empty lines.
|
||||||
remove_degenerate(loop_lines);
|
remove_degenerate(loop_lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the contact infill area to the interface area
|
// add the contact infill area to the interface area
|
||||||
// note that growing loops by $circle_radius ensures no tiny
|
// note that growing loops by $circle_radius ensures no tiny
|
||||||
// extrusions are left inside the circles; however it creates
|
// extrusions are left inside the circles; however it creates
|
||||||
|
@ -1183,7 +1184,7 @@ static void modulate_extrusion_by_overlapping_layers(
|
||||||
// Split the extrusions by the overlapping layers, reduce their extrusion rate.
|
// Split the extrusions by the overlapping layers, reduce their extrusion rate.
|
||||||
// The last path_fragment is from this_layer.
|
// The last path_fragment is from this_layer.
|
||||||
std::vector<ExtrusionPathFragment> path_fragments(
|
std::vector<ExtrusionPathFragment> path_fragments(
|
||||||
n_overlapping_layers + 1,
|
n_overlapping_layers + 1,
|
||||||
ExtrusionPathFragment(extrusion_path_template->mm3_per_mm, extrusion_path_template->width, extrusion_path_template->height));
|
ExtrusionPathFragment(extrusion_path_template->mm3_per_mm, extrusion_path_template->width, extrusion_path_template->height));
|
||||||
// Don't use it, it will be released.
|
// Don't use it, it will be released.
|
||||||
extrusion_path_template = nullptr;
|
extrusion_path_template = nullptr;
|
||||||
|
@ -1235,7 +1236,7 @@ static void modulate_extrusion_by_overlapping_layers(
|
||||||
#endif /* SLIC3R_DEBUG */
|
#endif /* SLIC3R_DEBUG */
|
||||||
|
|
||||||
// End points of the original paths.
|
// End points of the original paths.
|
||||||
std::vector<std::pair<Point, Point>> path_ends;
|
std::vector<std::pair<Point, Point>> path_ends;
|
||||||
// Collect the paths of this_layer.
|
// Collect the paths of this_layer.
|
||||||
{
|
{
|
||||||
Polylines &polylines = path_fragments.back().polylines;
|
Polylines &polylines = path_fragments.back().polylines;
|
||||||
|
@ -1452,7 +1453,7 @@ SupportGeneratorLayersPtr generate_support_layers(
|
||||||
height_min = std::min(height_min, layer.height);
|
height_min = std::min(height_min, layer.height);
|
||||||
}
|
}
|
||||||
if (! empty) {
|
if (! empty) {
|
||||||
// Here the upper_layer and lower_layer pointers are left to null at the support layers,
|
// Here the upper_layer and lower_layer pointers are left to null at the support layers,
|
||||||
// as they are never used. These pointers are candidates for removal.
|
// as they are never used. These pointers are candidates for removal.
|
||||||
bool this_layer_contacts_only = num_top_contacts > 0 && num_top_contacts == num_interfaces;
|
bool this_layer_contacts_only = num_top_contacts > 0 && num_top_contacts == num_interfaces;
|
||||||
size_t this_layer_id_interface = layer_id_interface;
|
size_t this_layer_id_interface = layer_id_interface;
|
||||||
|
@ -1627,12 +1628,12 @@ void generate_support_toolpaths(
|
||||||
// Pointer to the 1st layer interface filler.
|
// Pointer to the 1st layer interface filler.
|
||||||
auto filler_first_layer = filler_first_layer_ptr ? filler_first_layer_ptr.get() : filler_interface.get();
|
auto filler_first_layer = filler_first_layer_ptr ? filler_first_layer_ptr.get() : filler_interface.get();
|
||||||
// Filler for the 1st layer interface, if different from filler_interface.
|
// Filler for the 1st layer interface, if different from filler_interface.
|
||||||
auto filler_raft_contact_ptr = std::unique_ptr<Fill>(range.begin() == n_raft_layers && config.support_interface_top_layers.value == 0 ?
|
auto filler_raft_contact_ptr = std::unique_ptr<Fill>(range.begin() == n_raft_layers && config.support_interface_top_layers.value == 0 ?
|
||||||
Fill::new_from_type(support_params.raft_interface_fill_pattern) : nullptr);
|
Fill::new_from_type(support_params.raft_interface_fill_pattern) : nullptr);
|
||||||
// Pointer to the 1st layer interface filler.
|
// Pointer to the 1st layer interface filler.
|
||||||
auto filler_raft_contact = filler_raft_contact_ptr ? filler_raft_contact_ptr.get() : filler_interface.get();
|
auto filler_raft_contact = filler_raft_contact_ptr ? filler_raft_contact_ptr.get() : filler_interface.get();
|
||||||
// Filler for the base interface (to be used for soluble interface / non soluble base, to produce non soluble interface layer below soluble interface layer).
|
// Filler for the base interface (to be used for soluble interface / non soluble base, to produce non soluble interface layer below soluble interface layer).
|
||||||
auto filler_base_interface = std::unique_ptr<Fill>(base_interface_layers.empty() ? nullptr :
|
auto filler_base_interface = std::unique_ptr<Fill>(base_interface_layers.empty() ? nullptr :
|
||||||
Fill::new_from_type(support_params.interface_density > 0.95 || support_params.with_sheath ? ipRectilinear : ipSupportBase));
|
Fill::new_from_type(support_params.interface_density > 0.95 || support_params.with_sheath ? ipRectilinear : ipSupportBase));
|
||||||
auto filler_support = std::unique_ptr<Fill>(Fill::new_from_type(support_params.base_fill_pattern));
|
auto filler_support = std::unique_ptr<Fill>(Fill::new_from_type(support_params.base_fill_pattern));
|
||||||
filler_interface->set_bounding_box(bbox_object);
|
filler_interface->set_bounding_box(bbox_object);
|
||||||
|
@ -1695,7 +1696,7 @@ void generate_support_toolpaths(
|
||||||
// to trim other layers.
|
// to trim other layers.
|
||||||
if (top_contact_layer.could_merge(interface_layer) && ! raft_layer)
|
if (top_contact_layer.could_merge(interface_layer) && ! raft_layer)
|
||||||
top_contact_layer.merge(std::move(interface_layer));
|
top_contact_layer.merge(std::move(interface_layer));
|
||||||
}
|
}
|
||||||
if ((config.support_interface_top_layers == 0 || config.support_interface_bottom_layers == 0) && support_params.can_merge_support_regions) {
|
if ((config.support_interface_top_layers == 0 || config.support_interface_bottom_layers == 0) && support_params.can_merge_support_regions) {
|
||||||
if (base_layer.could_merge(bottom_contact_layer))
|
if (base_layer.could_merge(bottom_contact_layer))
|
||||||
base_layer.merge(std::move(bottom_contact_layer));
|
base_layer.merge(std::move(bottom_contact_layer));
|
||||||
|
@ -1729,14 +1730,14 @@ void generate_support_toolpaths(
|
||||||
auto *filler = raft_contact ? filler_raft_contact : filler_interface.get();
|
auto *filler = raft_contact ? filler_raft_contact : filler_interface.get();
|
||||||
auto interface_flow = layer_ex.layer->bridging ?
|
auto interface_flow = layer_ex.layer->bridging ?
|
||||||
Flow::bridging_flow(layer_ex.layer->height, support_params.support_material_bottom_interface_flow.nozzle_diameter()) :
|
Flow::bridging_flow(layer_ex.layer->height, support_params.support_material_bottom_interface_flow.nozzle_diameter()) :
|
||||||
(raft_contact ? &support_params.raft_interface_flow :
|
(raft_contact ? &support_params.raft_interface_flow :
|
||||||
interface_as_base ? &support_params.support_material_flow : &support_params.support_material_interface_flow)
|
interface_as_base ? &support_params.support_material_flow : &support_params.support_material_interface_flow)
|
||||||
->with_height(float(layer_ex.layer->height));
|
->with_height(float(layer_ex.layer->height));
|
||||||
filler->angle = interface_as_base ?
|
filler->angle = interface_as_base ?
|
||||||
// If zero interface layers are configured, use the same angle as for the base layers.
|
// If zero interface layers are configured, use the same angle as for the base layers.
|
||||||
angles[support_layer_id % angles.size()] :
|
angles[support_layer_id % angles.size()] :
|
||||||
// Use interface angle for the interface layers.
|
// Use interface angle for the interface layers.
|
||||||
raft_contact ?
|
raft_contact ?
|
||||||
support_params.raft_interface_angle(support_layer.interface_id()) :
|
support_params.raft_interface_angle(support_layer.interface_id()) :
|
||||||
support_interface_angle;
|
support_interface_angle;
|
||||||
double density = raft_contact ? support_params.raft_interface_density : interface_as_base ? support_params.support_density : support_params.interface_density;
|
double density = raft_contact ? support_params.raft_interface_density : interface_as_base ? support_params.support_density : support_params.interface_density;
|
||||||
|
@ -1745,7 +1746,7 @@ void generate_support_toolpaths(
|
||||||
filler->link_max_length = coord_t(scale_(filler->spacing * link_max_length_factor / density));
|
filler->link_max_length = coord_t(scale_(filler->spacing * link_max_length_factor / density));
|
||||||
fill_expolygons_generate_paths(
|
fill_expolygons_generate_paths(
|
||||||
// Destination
|
// Destination
|
||||||
layer_ex.extrusions,
|
layer_ex.extrusions,
|
||||||
// Regions to fill
|
// Regions to fill
|
||||||
union_safety_offset_ex(layer_ex.polygons_to_extrude()),
|
union_safety_offset_ex(layer_ex.polygons_to_extrude()),
|
||||||
// Filler and its parameters
|
// Filler and its parameters
|
||||||
|
@ -1772,7 +1773,7 @@ void generate_support_toolpaths(
|
||||||
filler->link_max_length = coord_t(scale_(filler->spacing * link_max_length_factor / support_params.interface_density));
|
filler->link_max_length = coord_t(scale_(filler->spacing * link_max_length_factor / support_params.interface_density));
|
||||||
fill_expolygons_generate_paths(
|
fill_expolygons_generate_paths(
|
||||||
// Destination
|
// Destination
|
||||||
base_interface_layer.extrusions,
|
base_interface_layer.extrusions,
|
||||||
//base_layer_interface.extrusions,
|
//base_layer_interface.extrusions,
|
||||||
// Regions to fill
|
// Regions to fill
|
||||||
union_safety_offset_ex(base_interface_layer.polygons_to_extrude()),
|
union_safety_offset_ex(base_interface_layer.polygons_to_extrude()),
|
||||||
|
@ -1927,7 +1928,7 @@ void PrintObjectSupportMaterial::clip_by_pillars(
|
||||||
|
|
||||||
coord_t pillar_size = scale_(PILLAR_SIZE);
|
coord_t pillar_size = scale_(PILLAR_SIZE);
|
||||||
coord_t pillar_spacing = scale_(PILLAR_SPACING);
|
coord_t pillar_spacing = scale_(PILLAR_SPACING);
|
||||||
|
|
||||||
// A regular grid of pillars, filling the 2D bounding box.
|
// A regular grid of pillars, filling the 2D bounding box.
|
||||||
Polygons grid;
|
Polygons grid;
|
||||||
{
|
{
|
||||||
|
@ -1937,7 +1938,7 @@ void PrintObjectSupportMaterial::clip_by_pillars(
|
||||||
pillar.points.push_back(Point(pillar_size, 0));
|
pillar.points.push_back(Point(pillar_size, 0));
|
||||||
pillar.points.push_back(Point(pillar_size, pillar_size));
|
pillar.points.push_back(Point(pillar_size, pillar_size));
|
||||||
pillar.points.push_back(Point(0, pillar_size));
|
pillar.points.push_back(Point(0, pillar_size));
|
||||||
|
|
||||||
// 2D bounding box of the projection of all contact polygons.
|
// 2D bounding box of the projection of all contact polygons.
|
||||||
BoundingBox bbox;
|
BoundingBox bbox;
|
||||||
for (LayersPtr::const_iterator it = top_contacts.begin(); it != top_contacts.end(); ++ it)
|
for (LayersPtr::const_iterator it = top_contacts.begin(); it != top_contacts.end(); ++ it)
|
||||||
|
@ -1951,30 +1952,30 @@ void PrintObjectSupportMaterial::clip_by_pillars(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add pillars to every layer
|
// add pillars to every layer
|
||||||
for my $i (0..n_support_z) {
|
for my $i (0..n_support_z) {
|
||||||
$shape->[$i] = [ @$grid ];
|
$shape->[$i] = [ @$grid ];
|
||||||
}
|
}
|
||||||
|
|
||||||
// build capitals
|
// build capitals
|
||||||
for my $i (0..n_support_z) {
|
for my $i (0..n_support_z) {
|
||||||
my $z = $support_z->[$i];
|
my $z = $support_z->[$i];
|
||||||
|
|
||||||
my $capitals = intersection(
|
my $capitals = intersection(
|
||||||
$grid,
|
$grid,
|
||||||
$contact->{$z} // [],
|
$contact->{$z} // [],
|
||||||
);
|
);
|
||||||
|
|
||||||
// work on one pillar at time (if any) to prevent the capitals from being merged
|
// work on one pillar at time (if any) to prevent the capitals from being merged
|
||||||
// but store the contact area supported by the capital because we need to make
|
// but store the contact area supported by the capital because we need to make
|
||||||
// sure nothing is left
|
// sure nothing is left
|
||||||
my $contact_supported_by_capitals = [];
|
my $contact_supported_by_capitals = [];
|
||||||
foreach my $capital (@$capitals) {
|
foreach my $capital (@$capitals) {
|
||||||
// enlarge capital tops
|
// enlarge capital tops
|
||||||
$capital = offset([$capital], +($pillar_spacing - $pillar_size)/2);
|
$capital = offset([$capital], +($pillar_spacing - $pillar_size)/2);
|
||||||
push @$contact_supported_by_capitals, @$capital;
|
push @$contact_supported_by_capitals, @$capital;
|
||||||
|
|
||||||
for (my $j = $i-1; $j >= 0; $j--) {
|
for (my $j = $i-1; $j >= 0; $j--) {
|
||||||
my $jz = $support_z->[$j];
|
my $jz = $support_z->[$j];
|
||||||
$capital = offset($capital, -$self->interface_flow->scaled_width/2);
|
$capital = offset($capital, -$self->interface_flow->scaled_width/2);
|
||||||
|
@ -1982,7 +1983,7 @@ void PrintObjectSupportMaterial::clip_by_pillars(
|
||||||
push @{ $shape->[$j] }, @$capital;
|
push @{ $shape->[$j] }, @$capital;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Capitals will not generally cover the whole contact area because there will be
|
// Capitals will not generally cover the whole contact area because there will be
|
||||||
// remainders. For now we handle this situation by projecting such unsupported
|
// remainders. For now we handle this situation by projecting such unsupported
|
||||||
// areas to the ground, just like we would do with a normal support.
|
// areas to the ground, just like we would do with a normal support.
|
||||||
|
@ -2000,10 +2001,10 @@ void PrintObjectSupportMaterial::clip_by_pillars(
|
||||||
|
|
||||||
sub clip_with_shape {
|
sub clip_with_shape {
|
||||||
my ($self, $support, $shape) = @_;
|
my ($self, $support, $shape) = @_;
|
||||||
|
|
||||||
foreach my $i (keys %$support) {
|
foreach my $i (keys %$support) {
|
||||||
// don't clip bottom layer with shape so that we
|
// don't clip bottom layer with shape so that we
|
||||||
// can generate a continuous base flange
|
// can generate a continuous base flange
|
||||||
// also don't clip raft layers
|
// also don't clip raft layers
|
||||||
next if $i == 0;
|
next if $i == 0;
|
||||||
next if $i < $self->object_config->raft_layers;
|
next if $i < $self->object_config->raft_layers;
|
||||||
|
|
|
@ -50,6 +50,8 @@ SupportGeneratorLayersPtr generate_raft_base(
|
||||||
const SupportGeneratorLayersPtr &base_layers,
|
const SupportGeneratorLayersPtr &base_layers,
|
||||||
SupportGeneratorLayerStorage &layer_storage);
|
SupportGeneratorLayerStorage &layer_storage);
|
||||||
|
|
||||||
|
void tree_supports_generate_paths(ExtrusionEntitiesPtr &dst, const Polygons &polygons, const Flow &flow, const SupportParameters &support_params);
|
||||||
|
|
||||||
void fill_expolygons_with_sheath_generate_paths(
|
void fill_expolygons_with_sheath_generate_paths(
|
||||||
ExtrusionEntitiesPtr &dst, const Polygons &polygons, Fill *filler, float density, ExtrusionRole role, const Flow &flow, const SupportParameters& support_params, bool with_sheath, bool no_sort);
|
ExtrusionEntitiesPtr &dst, const Polygons &polygons, Fill *filler, float density, ExtrusionRole role, const Flow &flow, const SupportParameters& support_params, bool with_sheath, bool no_sort);
|
||||||
|
|
||||||
|
|
|
@ -6,45 +6,42 @@
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
struct SupportParameters {
|
struct SupportParameters {
|
||||||
SupportParameters() = default;
|
SupportParameters() = delete;
|
||||||
SupportParameters(const PrintObject &object)
|
SupportParameters(const PrintObject& object)
|
||||||
{
|
{
|
||||||
const PrintConfig &print_config = object.print()->config();
|
const PrintConfig& print_config = object.print()->config();
|
||||||
const PrintObjectConfig &object_config = object.config();
|
const PrintObjectConfig& object_config = object.config();
|
||||||
const SlicingParameters &slicing_params = object.slicing_parameters();
|
const SlicingParameters& slicing_params = object.slicing_parameters();
|
||||||
|
|
||||||
this->soluble_interface = slicing_params.soluble_interface;
|
this->soluble_interface = slicing_params.soluble_interface;
|
||||||
this->soluble_interface_non_soluble_base =
|
this->soluble_interface_non_soluble_base =
|
||||||
// Zero z-gap between the overhangs and the support interface.
|
// Zero z-gap between the overhangs and the support interface.
|
||||||
slicing_params.soluble_interface &&
|
slicing_params.soluble_interface &&
|
||||||
// Interface extruder soluble.
|
// Interface extruder soluble.
|
||||||
object_config.support_interface_filament.value > 0 && print_config.filament_soluble.get_at(object_config.support_interface_filament.value - 1) &&
|
object_config.support_interface_filament.value > 0 && print_config.filament_soluble.get_at(object_config.support_interface_filament.value - 1) &&
|
||||||
// Base extruder: Either "print with active extruder" not soluble.
|
// Base extruder: Either "print with active extruder" not soluble.
|
||||||
(object_config.support_filament.value == 0 || ! print_config.filament_soluble.get_at(object_config.support_filament.value - 1));
|
(object_config.support_filament.value == 0 || ! print_config.filament_soluble.get_at(object_config.support_filament.value - 1));
|
||||||
|
|
||||||
{
|
{
|
||||||
int num_top_interface_layers = std::max(0, object_config.support_interface_top_layers.value);
|
this->num_top_interface_layers = std::max(0, object_config.support_interface_top_layers.value);
|
||||||
int num_bottom_interface_layers = object_config.support_interface_bottom_layers < 0 ?
|
this->num_bottom_interface_layers = object_config.support_interface_bottom_layers < 0 ?
|
||||||
num_top_interface_layers : object_config.support_interface_bottom_layers;
|
num_top_interface_layers : object_config.support_interface_bottom_layers;
|
||||||
this->has_top_contacts = num_top_interface_layers > 0;
|
this->has_top_contacts = num_top_interface_layers > 0;
|
||||||
this->has_bottom_contacts = num_bottom_interface_layers > 0;
|
this->has_bottom_contacts = num_bottom_interface_layers > 0;
|
||||||
this->num_top_interface_layers = this->has_top_contacts ? size_t(num_top_interface_layers - 1) : 0;
|
if (this->soluble_interface_non_soluble_base) {
|
||||||
this->num_bottom_interface_layers = this->has_bottom_contacts ? size_t(num_bottom_interface_layers - 1) : 0;
|
// Try to support soluble dense interfaces with non-soluble dense interfaces.
|
||||||
if (this->soluble_interface_non_soluble_base) {
|
this->num_top_base_interface_layers = size_t(std::min(int(num_top_interface_layers) / 2, 2));
|
||||||
// Try to support soluble dense interfaces with non-soluble dense interfaces.
|
this->num_bottom_base_interface_layers = size_t(std::min(int(num_bottom_interface_layers) / 2, 2));
|
||||||
this->num_top_base_interface_layers = size_t(std::min(num_top_interface_layers / 2, 2));
|
} else {
|
||||||
this->num_bottom_base_interface_layers = size_t(std::min(num_bottom_interface_layers / 2, 2));
|
this->num_top_base_interface_layers = 0;
|
||||||
} else {
|
this->num_bottom_base_interface_layers = 0;
|
||||||
this->num_top_base_interface_layers = 0;
|
}
|
||||||
this->num_bottom_base_interface_layers = 0;
|
}
|
||||||
}
|
this->first_layer_flow = Slic3r::support_material_1st_layer_flow(&object, float(slicing_params.first_print_layer_height));
|
||||||
}
|
this->support_material_flow = Slic3r::support_material_flow(&object, float(slicing_params.layer_height));
|
||||||
|
this->support_material_interface_flow = Slic3r::support_material_interface_flow(&object, float(slicing_params.layer_height));
|
||||||
this->first_layer_flow = Slic3r::support_material_1st_layer_flow(&object, float(slicing_params.first_print_layer_height));
|
this->raft_interface_flow = support_material_interface_flow;
|
||||||
this->support_material_flow = Slic3r::support_material_flow(&object, float(slicing_params.layer_height));
|
|
||||||
this->support_material_interface_flow = Slic3r::support_material_interface_flow(&object, float(slicing_params.layer_height));
|
|
||||||
this->raft_interface_flow = support_material_interface_flow;
|
|
||||||
|
|
||||||
// Calculate a minimum support layer height as a minimum over all extruders, but not smaller than 10um.
|
// Calculate a minimum support layer height as a minimum over all extruders, but not smaller than 10um.
|
||||||
this->support_layer_height_min = scaled<coord_t>(0.01);
|
this->support_layer_height_min = scaled<coord_t>(0.01);
|
||||||
for (auto lh : print_config.min_layer_height.values)
|
for (auto lh : print_config.min_layer_height.values)
|
||||||
|
@ -155,7 +152,8 @@ struct SupportParameters {
|
||||||
|
|
||||||
independent_layer_height = print_config.independent_support_layer_height;
|
independent_layer_height = print_config.independent_support_layer_height;
|
||||||
|
|
||||||
tree_branch_diameter_double_wall_area_scaled = 0.25 * sqr(scaled<double>(object_config.tree_support_branch_diameter_double_wall.value)) * M_PI;
|
// force double walls everywhere if wall count is larger than 1
|
||||||
|
tree_branch_diameter_double_wall_area_scaled = object_config.tree_support_wall_count.value > 1 ? 0.1 : 0.25 * sqr(scaled<double>(5.0)) * M_PI;
|
||||||
|
|
||||||
support_style = object_config.support_style;
|
support_style = object_config.support_style;
|
||||||
if (support_style == smsDefault) {
|
if (support_style == smsDefault) {
|
||||||
|
@ -236,7 +234,7 @@ struct SupportParameters {
|
||||||
// Shall the sparse (base) layers be printed with a single perimeter line (sheath) for robustness?
|
// Shall the sparse (base) layers be printed with a single perimeter line (sheath) for robustness?
|
||||||
bool with_sheath;
|
bool with_sheath;
|
||||||
// Branches of organic supports with area larger than this threshold will be extruded with double lines.
|
// Branches of organic supports with area larger than this threshold will be extruded with double lines.
|
||||||
double tree_branch_diameter_double_wall_area_scaled = 0.25 * sqr(scaled<double>(3.0)) * M_PI;;
|
double tree_branch_diameter_double_wall_area_scaled = 0.25 * sqr(scaled<double>(5.0)) * M_PI;;
|
||||||
|
|
||||||
float raft_angle_1st_layer;
|
float raft_angle_1st_layer;
|
||||||
float raft_angle_base;
|
float raft_angle_base;
|
||||||
|
|
|
@ -1541,12 +1541,16 @@ void TreeSupport::generate_toolpaths()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
size_t walls = wall_count;
|
size_t walls = wall_count;
|
||||||
if (area_group.need_extra_wall && walls < 2) walls += 1;
|
//if (area_group.need_extra_wall && walls < 2) walls += 1;
|
||||||
for (size_t i = 1; i < walls; i++) {
|
//for (size_t i = 1; i < walls; i++) {
|
||||||
Polygons contour_new = offset(poly.contour, -(i - 0.5f) * flow.scaled_spacing(), jtSquare);
|
// Polygons contour_new = offset(poly.contour, -(i - 0.5f) * flow.scaled_spacing(), jtSquare);
|
||||||
loops.insert(loops.end(), contour_new.begin(), contour_new.end());
|
// loops.insert(loops.end(), contour_new.begin(), contour_new.end());
|
||||||
}
|
//}
|
||||||
fill_expolygons_with_sheath_generate_paths(ts_layer->support_fills.entities, loops, nullptr, 0, erSupportMaterial, flow, m_support_params, true, false);
|
//fill_expolygons_with_sheath_generate_paths(ts_layer->support_fills.entities, loops, nullptr, 0, erSupportMaterial, flow, true, false);
|
||||||
|
SupportParameters support_params = m_support_params;
|
||||||
|
if(walls>1)
|
||||||
|
support_params.tree_branch_diameter_double_wall_area_scaled=0.1;
|
||||||
|
tree_supports_generate_paths(ts_layer->support_fills.entities, loops, flow, support_params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1606,8 +1610,12 @@ void TreeSupport::generate_toolpaths()
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort extrusions to reduce travel, also make sure walls go before infills
|
// sort extrusions to reduce travel, also make sure walls go before infills
|
||||||
if(ts_layer->support_fills.no_sort==false)
|
if (ts_layer->support_fills.no_sort == false) {
|
||||||
|
// chain_and_reorder_extrusion_entities crashes if there are empty elements in entities
|
||||||
|
auto &entities = ts_layer->support_fills.entities;
|
||||||
|
entities.erase(std::remove_if(entities.begin(), entities.end(), [](ExtrusionEntity* entity) { return static_cast<ExtrusionEntityCollection*>(entity)->empty(); }), entities.end());
|
||||||
chain_and_reorder_extrusion_entities(ts_layer->support_fills.entities);
|
chain_and_reorder_extrusion_entities(ts_layer->support_fills.entities);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -3434,6 +3434,7 @@ static void generate_support_areas(Print &print, TreeSupport* tree_support, cons
|
||||||
// The trees will have the density zeroed in tree_supports_generate_paths()
|
// The trees will have the density zeroed in tree_supports_generate_paths()
|
||||||
// support_params.support_density = 0;
|
// support_params.support_density = 0;
|
||||||
|
|
||||||
|
|
||||||
SupportGeneratorLayerStorage layer_storage;
|
SupportGeneratorLayerStorage layer_storage;
|
||||||
SupportGeneratorLayersPtr top_contacts;
|
SupportGeneratorLayersPtr top_contacts;
|
||||||
SupportGeneratorLayersPtr bottom_contacts;
|
SupportGeneratorLayersPtr bottom_contacts;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue