ENH: open support wall count for normal support
1. open support wall count for normal support Enabling this option makes normal support stronger and gives better overhang quality, but also more difficult to removal. Jira: STUDIO-5192 2. fix a bug where tree support (hybrid style) may get overlapped extrusions near the walls. 3. fix a bug where raft layers can't be 1 in tree support Jira: STUDIO-5261 Change-Id: Iadc0c67a9b50b5b221c8e83d5aa22ed282018cf8 (cherry picked from commit c0bb0084e386cb70ed6e16edf93190e4b38f5b90)
This commit is contained in:
parent
fc24aa6ead
commit
bf93fd02fb
|
@ -9114,11 +9114,11 @@ msgstr "树状支撑分支直径"
|
||||||
msgid "This setting determines the initial diameter of support nodes."
|
msgid "This setting determines the initial diameter of support nodes."
|
||||||
msgstr "此设置确定了树状支撑节点的初始直径。"
|
msgstr "此设置确定了树状支撑节点的初始直径。"
|
||||||
|
|
||||||
msgid "Tree support wall loops"
|
msgid "Support wall loops"
|
||||||
msgstr "树状支撑外墙层数"
|
msgstr "支撑外墙层数"
|
||||||
|
|
||||||
msgid "This setting specify the count of walls around tree support"
|
msgid "This setting specify the count of walls around support"
|
||||||
msgstr "树状支撑外墙层数"
|
msgstr "此设置指定了支撑的外墙层数"
|
||||||
|
|
||||||
msgid "Tree support brim width"
|
msgid "Tree support brim width"
|
||||||
msgstr "树状支撑裙边宽度"
|
msgstr "树状支撑裙边宽度"
|
||||||
|
|
|
@ -3272,11 +3272,11 @@ void PrintConfigDef::init_fff_params()
|
||||||
def->set_default_value(new ConfigOptionFloat(5.));
|
def->set_default_value(new ConfigOptionFloat(5.));
|
||||||
|
|
||||||
def = this->add("tree_support_wall_count", coInt);
|
def = this->add("tree_support_wall_count", coInt);
|
||||||
def->label = L("Tree 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 tree support");
|
def->tooltip = L("This setting specify the count of walls around support");
|
||||||
def->min = 0;
|
def->min = 0;
|
||||||
def->mode = comDevelop;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionInt(1));
|
def->set_default_value(new ConfigOptionInt(1));
|
||||||
|
|
||||||
def = this->add("tree_support_brim_width", coFloat);
|
def = this->add("tree_support_brim_width", coFloat);
|
||||||
|
|
|
@ -97,7 +97,7 @@ struct SupportParameters {
|
||||||
}
|
}
|
||||||
|
|
||||||
SupportMaterialPattern support_pattern = object_config.support_base_pattern;
|
SupportMaterialPattern support_pattern = object_config.support_base_pattern;
|
||||||
this->with_sheath = is_tree(object_config.support_type) && object_config.tree_support_wall_count > 0;
|
this->with_sheath = /*is_tree(object_config.support_type) &&*/ object_config.tree_support_wall_count > 0;
|
||||||
this->base_fill_pattern =
|
this->base_fill_pattern =
|
||||||
support_pattern == smpHoneycomb ? ipHoneycomb :
|
support_pattern == smpHoneycomb ? ipHoneycomb :
|
||||||
this->support_density > 0.95 || this->with_sheath ? ipRectilinear : ipSupportBase;
|
this->support_density > 0.95 || this->with_sheath ? ipRectilinear : ipSupportBase;
|
||||||
|
|
|
@ -19,11 +19,6 @@
|
||||||
#include "BuildVolume.hpp"
|
#include "BuildVolume.hpp"
|
||||||
#include "ClipperUtils.hpp"
|
#include "ClipperUtils.hpp"
|
||||||
|
|
||||||
#define _L(s) Slic3r::I18N::translate(s)
|
|
||||||
|
|
||||||
#define USE_PLAN_LAYER_HEIGHTS 1
|
|
||||||
#define HEIGHT_TO_SWITCH_INFILL_DIRECTION 30 // change infill direction every 20mm
|
|
||||||
|
|
||||||
#ifndef M_PI
|
#ifndef M_PI
|
||||||
#define M_PI 3.1415926535897932384626433832795
|
#define M_PI 3.1415926535897932384626433832795
|
||||||
#endif
|
#endif
|
||||||
|
@ -173,7 +168,7 @@ Lines spanning_tree_to_lines(const std::vector<MinimumSpanningTree>& spanning_tr
|
||||||
|
|
||||||
|
|
||||||
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
||||||
static std::string get_svg_filename(std::string layer_nr_or_z, std::string tag = "bbl_ts")
|
static std::string get_svg_filename(const std::string& tag = "bbl_ts", const std::string& layer_nr_or_z="")
|
||||||
{
|
{
|
||||||
static bool rand_init = false;
|
static bool rand_init = false;
|
||||||
|
|
||||||
|
@ -183,10 +178,13 @@ static std::string get_svg_filename(std::string layer_nr_or_z, std::string tag
|
||||||
}
|
}
|
||||||
|
|
||||||
int rand_num = rand() % 1000000;
|
int rand_num = rand() % 1000000;
|
||||||
//makedir("./SVG");
|
std::string prefix = "C:/Users/arthur.tang/AppData/Roaming/BambuStudioInternal/SVG/";
|
||||||
std::string prefix = "./SVG/";
|
//makedir(prefix);
|
||||||
std::string suffix = ".svg";
|
std::string suffix = ".svg";
|
||||||
return prefix + tag + "_" + layer_nr_or_z /*+ "_" + std::to_string(rand_num)*/ + suffix;
|
std::string name = prefix + tag;
|
||||||
|
if(!layer_nr_or_z.empty())
|
||||||
|
name+= "_" + layer_nr_or_z;
|
||||||
|
return name + suffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_contours_and_nodes_to_svg
|
static void draw_contours_and_nodes_to_svg
|
||||||
|
@ -214,10 +212,7 @@ static void draw_contours_and_nodes_to_svg
|
||||||
bbox.max.y() = std::max(bbox.max.y(), (coord_t)scale_(10));
|
bbox.max.y() = std::max(bbox.max.y(), (coord_t)scale_(10));
|
||||||
|
|
||||||
SVG svg;
|
SVG svg;
|
||||||
if(!layer_nr_or_z.empty())
|
svg.open(get_svg_filename(name_prefix, layer_nr_or_z), bbox);
|
||||||
svg.open(get_svg_filename(layer_nr_or_z, name_prefix), bbox);
|
|
||||||
else
|
|
||||||
svg.open(name_prefix, bbox);
|
|
||||||
if (!svg.is_opened()) return;
|
if (!svg.is_opened()) return;
|
||||||
|
|
||||||
// draw grid
|
// draw grid
|
||||||
|
@ -273,7 +268,7 @@ static void draw_layer_mst
|
||||||
bbox.merge(bb);
|
bbox.merge(bb);
|
||||||
}
|
}
|
||||||
|
|
||||||
SVG svg(get_svg_filename(layer_nr_or_z, "mstree").c_str(), bbox);
|
SVG svg(get_svg_filename("mstree",layer_nr_or_z).c_str(), bbox);
|
||||||
if (!svg.is_opened()) return;
|
if (!svg.is_opened()) return;
|
||||||
|
|
||||||
svg.draw(lines, "blue", coord_t(scale_(0.05)));
|
svg.draw(lines, "blue", coord_t(scale_(0.05)));
|
||||||
|
@ -290,7 +285,7 @@ static void draw_two_overhangs_to_svg(SupportLayer* ts_layer, const ExPolygons&
|
||||||
BoundingBox bbox2 = get_extents(overhangs2);
|
BoundingBox bbox2 = get_extents(overhangs2);
|
||||||
bbox1.merge(bbox2);
|
bbox1.merge(bbox2);
|
||||||
|
|
||||||
SVG svg(get_svg_filename(std::to_string(ts_layer->print_z), "two_overhangs"), bbox1);
|
SVG svg(get_svg_filename("two_overhangs", std::to_string(ts_layer->print_z)), bbox1);
|
||||||
if (!svg.is_opened()) return;
|
if (!svg.is_opened()) return;
|
||||||
|
|
||||||
svg.draw(union_ex(overhangs1), "blue");
|
svg.draw(union_ex(overhangs1), "blue");
|
||||||
|
@ -303,7 +298,7 @@ static void draw_polylines(SupportLayer* ts_layer, Polylines& polylines)
|
||||||
return;
|
return;
|
||||||
BoundingBox bbox = get_extents(polylines);
|
BoundingBox bbox = get_extents(polylines);
|
||||||
|
|
||||||
SVG svg(get_svg_filename(std::to_string(ts_layer->print_z), "lightnings"), bbox);
|
SVG svg(get_svg_filename("lightnings", std::to_string(ts_layer->print_z)), bbox);
|
||||||
if (!svg.is_opened()) return;
|
if (!svg.is_opened()) return;
|
||||||
|
|
||||||
int id = 0;
|
int id = 0;
|
||||||
|
@ -707,7 +702,7 @@ TreeSupport::TreeSupport(PrintObject& object, const SlicingParameters &slicing_p
|
||||||
m_support_params.independent_layer_height = false; // do not use independent layer height for 3D tree support
|
m_support_params.independent_layer_height = false; // do not use independent layer height for 3D tree support
|
||||||
#endif
|
#endif
|
||||||
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
||||||
SVG svg("SVG/machine_boarder.svg", m_object->bounding_box());
|
SVG svg(get_svg_filename("machine_boarder"), m_object->bounding_box());
|
||||||
if (svg.is_opened()) svg.draw(m_machine_border, "yellow");
|
if (svg.is_opened()) svg.draw(m_machine_border, "yellow");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -903,7 +898,7 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only)
|
||||||
if (!overhang.empty()) {
|
if (!overhang.empty()) {
|
||||||
has_sharp_tails = true;
|
has_sharp_tails = true;
|
||||||
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
||||||
SVG svg(format("SVG/sharp_tail_orig_%.02f.svg", layer->print_z), m_object->bounding_box());
|
SVG svg(get_svg_filename(format("sharp_tail_orig_%.02f", layer->print_z)), m_object->bounding_box());
|
||||||
if (svg.is_opened()) svg.draw(overhang, "red");
|
if (svg.is_opened()) svg.draw(overhang, "red");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -1020,7 +1015,7 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only)
|
||||||
if (!overhang.empty())
|
if (!overhang.empty())
|
||||||
has_sharp_tails = true;
|
has_sharp_tails = true;
|
||||||
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
||||||
SVG svg(format("SVG/sharp_tail_%.02f.svg",layer->print_z), m_object->bounding_box());
|
SVG svg(get_svg_filename(format("sharp_tail_%.02f",layer->print_z)), m_object->bounding_box());
|
||||||
if (svg.is_opened()) svg.draw(overhang, "red");
|
if (svg.is_opened()) svg.draw(overhang, "red");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -1033,6 +1028,8 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only)
|
||||||
for (size_t layer_nr = 0; layer_nr < m_object->layer_count(); layer_nr++) {
|
for (size_t layer_nr = 0; layer_nr < m_object->layer_count(); layer_nr++) {
|
||||||
if (m_object->print()->canceled())
|
if (m_object->print()->canceled())
|
||||||
break;
|
break;
|
||||||
|
if(layer_nr+m_raft_layers>=m_object->support_layer_count())
|
||||||
|
break;
|
||||||
SupportLayer* ts_layer = m_object->get_support_layer(layer_nr + m_raft_layers);
|
SupportLayer* ts_layer = m_object->get_support_layer(layer_nr + m_raft_layers);
|
||||||
Layer* layer = m_object->get_layer(layer_nr);
|
Layer* layer = m_object->get_layer(layer_nr);
|
||||||
for (auto& overhang : ts_layer->overhang_areas) {
|
for (auto& overhang : ts_layer->overhang_areas) {
|
||||||
|
@ -1073,9 +1070,9 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only)
|
||||||
const Layer* layer1 = m_object->get_layer(cluster.min_layer);
|
const Layer* layer1 = m_object->get_layer(cluster.min_layer);
|
||||||
BoundingBox bbox = cluster.merged_bbox;
|
BoundingBox bbox = cluster.merged_bbox;
|
||||||
bbox.merge(get_extents(layer1->lslices));
|
bbox.merge(get_extents(layer1->lslices));
|
||||||
SVG svg(format("SVG/overhangCluster_%s-%s_%s-%s_tail=%s_cantilever=%s_small=%s.svg",
|
SVG svg(get_svg_filename(format("overhangCluster_%s-%s_%s-%s_tail=%s_cantilever=%s_small=%s",
|
||||||
cluster.min_layer, cluster.max_layer, layer1->print_z, m_object->get_layer(cluster.max_layer)->print_z,
|
cluster.min_layer, cluster.max_layer, layer1->print_z, m_object->get_layer(cluster.max_layer)->print_z,
|
||||||
cluster.is_sharp_tail, cluster.is_cantilever, cluster.is_small_overhang), bbox);
|
cluster.is_sharp_tail, cluster.is_cantilever, cluster.is_small_overhang)), bbox);
|
||||||
if (svg.is_opened()) {
|
if (svg.is_opened()) {
|
||||||
svg.draw(layer1->lslices, "red");
|
svg.draw(layer1->lslices, "red");
|
||||||
svg.draw(cluster.merged_poly, "blue");
|
svg.draw(cluster.merged_poly, "blue");
|
||||||
|
@ -1121,8 +1118,9 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (max_bridge_length > 0 && ts_layer->overhang_areas.size() > 0 && lower_layer) {
|
if (max_bridge_length > 0 && ts_layer->overhang_areas.size() > 0 && lower_layer) {
|
||||||
// do not break bridge for normal part in TreeHybrid
|
// do not break bridge for normal part in TreeHybrid, nor Tree Strong
|
||||||
bool break_bridge = !(support_style == smsTreeHybrid && area(ts_layer->overhang_areas) > m_support_params.thresh_big_overhang);
|
bool break_bridge = !(support_style == smsTreeHybrid && area(ts_layer->overhang_areas) > m_support_params.thresh_big_overhang)
|
||||||
|
&& !(support_style==smsTreeStrong);
|
||||||
m_object->remove_bridges_from_contacts(lower_layer, layer, extrusion_width_scaled, &ts_layer->overhang_areas, max_bridge_length, break_bridge);
|
m_object->remove_bridges_from_contacts(lower_layer, layer, extrusion_width_scaled, &ts_layer->overhang_areas, max_bridge_length, break_bridge);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1156,7 +1154,7 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only)
|
||||||
if (layer->overhang_areas.empty() && (blockers.size()<=layer->id() || blockers[layer->id()].empty()))
|
if (layer->overhang_areas.empty() && (blockers.size()<=layer->id() || blockers[layer->id()].empty()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
SVG svg(format("SVG/overhang_areas_%s.svg", layer->print_z), m_object->bounding_box());
|
SVG svg(get_svg_filename("overhang_areas", std::to_string(layer->print_z)), m_object->bounding_box());
|
||||||
if (svg.is_opened()) {
|
if (svg.is_opened()) {
|
||||||
svg.draw_outline(m_object->get_layer(layer->id())->lslices, "yellow");
|
svg.draw_outline(m_object->get_layer(layer->id())->lslices, "yellow");
|
||||||
svg.draw(layer->overhang_areas, "orange");
|
svg.draw(layer->overhang_areas, "orange");
|
||||||
|
@ -1183,40 +1181,48 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only)
|
||||||
|
|
||||||
void TreeSupport::create_tree_support_layers()
|
void TreeSupport::create_tree_support_layers()
|
||||||
{
|
{
|
||||||
{ //create raft layers
|
|
||||||
int layer_id = 0;
|
int layer_id = 0;
|
||||||
|
{ //create raft layers
|
||||||
coordf_t raft_print_z = 0.f;
|
coordf_t raft_print_z = 0.f;
|
||||||
coordf_t raft_slice_z = 0.f;
|
coordf_t raft_slice_z = 0.f;
|
||||||
// Insert the base layers.
|
{
|
||||||
for (size_t i = 0; i < m_slicing_params.base_raft_layers; i++, layer_id++) {
|
// Do not add the raft contact layer, 1st layer should use first_print_layer_height
|
||||||
// 1st layer should use first_print_layer_height
|
coordf_t height = m_slicing_params.first_print_layer_height;
|
||||||
coordf_t height = i == 0 ? m_slicing_params.first_print_layer_height : m_slicing_params.base_raft_layer_height;
|
|
||||||
raft_print_z += height;
|
raft_print_z += height;
|
||||||
raft_slice_z = raft_print_z - height / 2;
|
raft_slice_z = raft_print_z - height / 2;
|
||||||
m_object->add_tree_support_layer(layer_id, height, raft_print_z, raft_slice_z);
|
m_object->add_tree_support_layer(layer_id++, height, raft_print_z, raft_slice_z);
|
||||||
|
}
|
||||||
|
// Insert the base layers.
|
||||||
|
for (size_t i = 1; i < m_slicing_params.base_raft_layers; i++) {
|
||||||
|
coordf_t height = m_slicing_params.base_raft_layer_height;
|
||||||
|
raft_print_z += height;
|
||||||
|
raft_slice_z = raft_print_z - height / 2;
|
||||||
|
m_object->add_tree_support_layer(layer_id++, height, raft_print_z, raft_slice_z);
|
||||||
}
|
}
|
||||||
// Insert the interface layers.
|
// Insert the interface layers.
|
||||||
for (size_t i = 0; i < m_slicing_params.interface_raft_layers; i++, layer_id++) {
|
for (size_t i = 0; i < m_slicing_params.interface_raft_layers; i++) {
|
||||||
coordf_t height = m_slicing_params.interface_raft_layer_height;
|
coordf_t height = m_slicing_params.interface_raft_layer_height;
|
||||||
raft_print_z += height;
|
raft_print_z += height;
|
||||||
raft_slice_z = raft_print_z - height / 2;
|
raft_slice_z = raft_print_z - height / 2;
|
||||||
m_object->add_tree_support_layer(layer_id, height, raft_print_z, raft_slice_z);
|
m_object->add_tree_support_layer(layer_id++, height, raft_print_z, raft_slice_z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Layer *layer : m_object->layers()) {
|
for (Layer *layer : m_object->layers()) {
|
||||||
SupportLayer* ts_layer = m_object->add_tree_support_layer(layer->id(), layer->height, layer->print_z, layer->slice_z);
|
SupportLayer* ts_layer = m_object->add_tree_support_layer(layer_id++, layer->height, layer->print_z, layer->slice_z);
|
||||||
if (ts_layer->id() > m_raft_layers) {
|
if (ts_layer->id() > m_raft_layers) {
|
||||||
SupportLayer* lower_layer = m_object->get_support_layer(ts_layer->id() - 1);
|
SupportLayer* lower_layer = m_object->get_support_layer(ts_layer->id() - 1);
|
||||||
|
if (lower_layer) {
|
||||||
lower_layer->upper_layer = ts_layer;
|
lower_layer->upper_layer = ts_layer;
|
||||||
ts_layer->lower_layer = lower_layer;
|
ts_layer->lower_layer = lower_layer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline BoundingBox fill_expolygon_generate_paths(
|
static inline BoundingBox fill_expolygon_generate_paths(
|
||||||
ExtrusionEntitiesPtr &dst,
|
ExtrusionEntitiesPtr &dst,
|
||||||
ExPolygon &&expolygon,
|
ExPolygon &expolygon,
|
||||||
Fill *filler,
|
Fill *filler,
|
||||||
const FillParams &fill_params,
|
const FillParams &fill_params,
|
||||||
ExtrusionRole role,
|
ExtrusionRole role,
|
||||||
|
@ -1243,7 +1249,7 @@ static inline BoundingBox fill_expolygon_generate_paths(
|
||||||
|
|
||||||
static inline std::vector<BoundingBox> fill_expolygons_generate_paths(
|
static inline std::vector<BoundingBox> fill_expolygons_generate_paths(
|
||||||
ExtrusionEntitiesPtr &dst,
|
ExtrusionEntitiesPtr &dst,
|
||||||
ExPolygons &&expolygons,
|
ExPolygons &expolygons,
|
||||||
Fill *filler,
|
Fill *filler,
|
||||||
const FillParams &fill_params,
|
const FillParams &fill_params,
|
||||||
ExtrusionRole role,
|
ExtrusionRole role,
|
||||||
|
@ -1405,16 +1411,9 @@ void TreeSupport::generate_toolpaths()
|
||||||
// generate raft tool path
|
// generate raft tool path
|
||||||
if (m_raft_layers > 0)
|
if (m_raft_layers > 0)
|
||||||
{
|
{
|
||||||
ExtrusionRole raft_contour_er = m_slicing_params.base_raft_layers > 0 ? erSupportMaterial : erSupportMaterialInterface;
|
|
||||||
SupportLayer *ts_layer = m_object->support_layers().front();
|
SupportLayer *ts_layer = m_object->support_layers().front();
|
||||||
Flow flow = Flow(support_extrusion_width, ts_layer->height, nozzle_diameter);
|
Flow flow = Flow(support_extrusion_width, ts_layer->height, nozzle_diameter);
|
||||||
|
extrusion_entities_append_loops(ts_layer->support_fills.entities, to_polygons(raft_areas), erSupportMaterial,
|
||||||
Polygons loops;
|
|
||||||
for (const ExPolygon& expoly : raft_areas) {
|
|
||||||
loops.push_back(expoly.contour);
|
|
||||||
loops.insert(loops.end(), expoly.holes.begin(), expoly.holes.end());
|
|
||||||
}
|
|
||||||
extrusion_entities_append_loops(ts_layer->support_fills.entities, std::move(loops), raft_contour_er,
|
|
||||||
float(flow.mm3_per_mm()), float(flow.width()), float(flow.height()));
|
float(flow.mm3_per_mm()), float(flow.width()), float(flow.height()));
|
||||||
raft_areas = offset_ex(raft_areas, -flow.scaled_spacing() / 2.);
|
raft_areas = offset_ex(raft_areas, -flow.scaled_spacing() / 2.);
|
||||||
}
|
}
|
||||||
|
@ -1422,6 +1421,7 @@ void TreeSupport::generate_toolpaths()
|
||||||
for (size_t layer_nr = 0; layer_nr < m_slicing_params.base_raft_layers; layer_nr++) {
|
for (size_t layer_nr = 0; layer_nr < m_slicing_params.base_raft_layers; layer_nr++) {
|
||||||
SupportLayer *ts_layer = m_object->get_support_layer(layer_nr);
|
SupportLayer *ts_layer = m_object->get_support_layer(layer_nr);
|
||||||
coordf_t expand_offset = (layer_nr == 0 ? 0. : -1.);
|
coordf_t expand_offset = (layer_nr == 0 ? 0. : -1.);
|
||||||
|
raft_areas = offset_ex(raft_areas, scale_(expand_offset));
|
||||||
|
|
||||||
Flow support_flow = Flow(support_extrusion_width, ts_layer->height, nozzle_diameter);
|
Flow support_flow = Flow(support_extrusion_width, ts_layer->height, nozzle_diameter);
|
||||||
Fill* filler_interface = Fill::new_from_type(ipRectilinear);
|
Fill* filler_interface = Fill::new_from_type(ipRectilinear);
|
||||||
|
@ -1432,16 +1432,25 @@ void TreeSupport::generate_toolpaths()
|
||||||
fill_params.density = object_config.raft_first_layer_density * 0.01;
|
fill_params.density = object_config.raft_first_layer_density * 0.01;
|
||||||
fill_params.dont_adjust = true;
|
fill_params.dont_adjust = true;
|
||||||
|
|
||||||
fill_expolygons_generate_paths(ts_layer->support_fills.entities, std::move(offset_ex(raft_areas, scale_(expand_offset))),
|
fill_expolygons_generate_paths(ts_layer->support_fills.entities, raft_areas,
|
||||||
filler_interface, fill_params, erSupportMaterial, support_flow);
|
filler_interface, fill_params, erSupportMaterial, support_flow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// subtract the non-raft support bases, otherwise we'll get support base on top of raft interfaces which is not stable
|
||||||
|
SupportLayer* first_non_raft_layer = m_object->get_support_layer(m_raft_layers);
|
||||||
|
ExPolygons first_non_raft_base;
|
||||||
|
for (auto& area_group : first_non_raft_layer->area_groups) {
|
||||||
|
if (area_group.type == SupportLayer::BaseType)
|
||||||
|
first_non_raft_base.emplace_back(*area_group.area);
|
||||||
|
}
|
||||||
|
ExPolygons raft_base_areas = intersection_ex(raft_areas, first_non_raft_base);
|
||||||
|
ExPolygons raft_interface_areas = diff_ex(raft_areas, raft_base_areas);
|
||||||
|
|
||||||
for (size_t layer_nr = m_slicing_params.base_raft_layers;
|
for (size_t layer_nr = m_slicing_params.base_raft_layers;
|
||||||
layer_nr < m_slicing_params.base_raft_layers + m_slicing_params.interface_raft_layers;
|
layer_nr < m_slicing_params.base_raft_layers + m_slicing_params.interface_raft_layers;
|
||||||
layer_nr++)
|
layer_nr++)
|
||||||
{
|
{
|
||||||
SupportLayer *ts_layer = m_object->get_support_layer(layer_nr);
|
SupportLayer *ts_layer = m_object->get_support_layer(layer_nr);
|
||||||
coordf_t expand_offset = (layer_nr == 0 ? 0. : -1.);
|
|
||||||
|
|
||||||
Flow support_flow(support_extrusion_width, ts_layer->height, nozzle_diameter);
|
Flow support_flow(support_extrusion_width, ts_layer->height, nozzle_diameter);
|
||||||
Fill* filler_interface = Fill::new_from_type(ipRectilinear);
|
Fill* filler_interface = Fill::new_from_type(ipRectilinear);
|
||||||
|
@ -1452,8 +1461,12 @@ void TreeSupport::generate_toolpaths()
|
||||||
fill_params.density = interface_density;
|
fill_params.density = interface_density;
|
||||||
fill_params.dont_adjust = true;
|
fill_params.dont_adjust = true;
|
||||||
|
|
||||||
fill_expolygons_generate_paths(ts_layer->support_fills.entities, std::move(offset_ex(raft_areas, scale_(expand_offset))),
|
fill_expolygons_generate_paths(ts_layer->support_fills.entities, raft_interface_areas,
|
||||||
filler_interface, fill_params, erSupportMaterialInterface, support_flow);
|
filler_interface, fill_params, erSupportMaterialInterface, support_flow);
|
||||||
|
|
||||||
|
fill_params.density = object_config.raft_first_layer_density * 0.01;
|
||||||
|
fill_expolygons_generate_paths(ts_layer->support_fills.entities, raft_base_areas,
|
||||||
|
filler_interface, fill_params, erSupportMaterial, support_flow);
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundingBox bbox_object(Point(-scale_(1.), -scale_(1.0)), Point(scale_(1.), scale_(1.)));
|
BoundingBox bbox_object(Point(-scale_(1.), -scale_(1.0)), Point(scale_(1.), scale_(1.)));
|
||||||
|
@ -1474,7 +1487,7 @@ void TreeSupport::generate_toolpaths()
|
||||||
if (m_object->print()->canceled())
|
if (m_object->print()->canceled())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
m_object->print()->set_status(70, (boost::format(_L("Support: generate toolpath at layer %d")) % layer_id).str());
|
m_object->print()->set_status(70, (boost::format(_u8L("Support: generate toolpath at layer %d")) % layer_id).str());
|
||||||
|
|
||||||
SupportLayer* ts_layer = m_object->get_support_layer(layer_id);
|
SupportLayer* ts_layer = m_object->get_support_layer(layer_id);
|
||||||
Flow support_flow(support_extrusion_width, ts_layer->height, nozzle_diameter);
|
Flow support_flow(support_extrusion_width, ts_layer->height, nozzle_diameter);
|
||||||
|
@ -1542,9 +1555,6 @@ void TreeSupport::generate_toolpaths()
|
||||||
bool need_infill = with_infill;
|
bool need_infill = with_infill;
|
||||||
if(m_object_config->support_base_pattern==smpDefault)
|
if(m_object_config->support_base_pattern==smpDefault)
|
||||||
need_infill &= area_group.need_infill;
|
need_infill &= area_group.need_infill;
|
||||||
size_t walls = wall_count;
|
|
||||||
if (layer_id == 0) walls = std::numeric_limits<size_t>::max();
|
|
||||||
else if (area_group.need_extra_wall && walls < 2) walls += 1;
|
|
||||||
|
|
||||||
std::shared_ptr<Fill> filler_support = std::shared_ptr<Fill>(Fill::new_from_type(layer_id == 0 ? ipConcentric : m_support_params.base_fill_pattern));
|
std::shared_ptr<Fill> filler_support = std::shared_ptr<Fill>(Fill::new_from_type(layer_id == 0 ? ipConcentric : m_support_params.base_fill_pattern));
|
||||||
filler_support->set_bounding_box(bbox_object);
|
filler_support->set_bounding_box(bbox_object);
|
||||||
|
@ -1560,11 +1570,14 @@ void TreeSupport::generate_toolpaths()
|
||||||
if (need_infill && m_support_params.base_fill_pattern != ipLightning) {
|
if (need_infill && m_support_params.base_fill_pattern != ipLightning) {
|
||||||
// allow infill-only mode if support is thick enough (so min_wall_count is 0);
|
// allow infill-only mode if support is thick enough (so min_wall_count is 0);
|
||||||
// otherwise must draw 1 wall
|
// otherwise must draw 1 wall
|
||||||
|
// Don't need extra walls if we have infill. Extra walls may overlap with the infills.
|
||||||
size_t min_wall_count = offset(poly, -scale_(support_spacing * 1.5)).empty() ? 1 : 0;
|
size_t min_wall_count = offset(poly, -scale_(support_spacing * 1.5)).empty() ? 1 : 0;
|
||||||
make_perimeter_and_infill(ts_layer->support_fills.entities, *m_object->print(), poly, std::max(min_wall_count, walls), flow,
|
make_perimeter_and_infill(ts_layer->support_fills.entities, *m_object->print(), poly, std::max(min_wall_count, wall_count), flow,
|
||||||
erSupportMaterial, filler_support.get(), support_density);
|
erSupportMaterial, filler_support.get(), support_density);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
size_t walls = wall_count;
|
||||||
|
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());
|
||||||
|
@ -1616,7 +1629,7 @@ void TreeSupport::generate_toolpaths()
|
||||||
float(flow.mm3_per_mm()), float(flow.width()), float(flow.height()));
|
float(flow.mm3_per_mm()), float(flow.width()), float(flow.height()));
|
||||||
|
|
||||||
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
||||||
std::string name = "./SVG/trees_polyline_" + std::to_string(ts_layer->print_z) /*+ "_" + std::to_string(rand_num)*/ + ".svg";
|
std::string name = get_svg_filename("trees_polyline", std::to_string(ts_layer->print_z));
|
||||||
BoundingBox bbox = get_extents(ts_layer->base_areas);
|
BoundingBox bbox = get_extents(ts_layer->base_areas);
|
||||||
SVG svg(name, bbox);
|
SVG svg(name, bbox);
|
||||||
if (svg.is_opened()) {
|
if (svg.is_opened()) {
|
||||||
|
@ -1870,7 +1883,7 @@ void TreeSupport::generate()
|
||||||
|
|
||||||
// Generate overhang areas
|
// Generate overhang areas
|
||||||
profiler.stage_start(STAGE_DETECT_OVERHANGS);
|
profiler.stage_start(STAGE_DETECT_OVERHANGS);
|
||||||
m_object->print()->set_status(55, _L("Support: detect overhangs"));
|
m_object->print()->set_status(55, _u8L("Support: detect overhangs"));
|
||||||
detect_overhangs();
|
detect_overhangs();
|
||||||
profiler.stage_finish(STAGE_DETECT_OVERHANGS);
|
profiler.stage_finish(STAGE_DETECT_OVERHANGS);
|
||||||
|
|
||||||
|
@ -1883,7 +1896,7 @@ void TreeSupport::generate()
|
||||||
std::vector<TreeSupport3D::SupportElements> move_bounds(m_highest_overhang_layer + 1);
|
std::vector<TreeSupport3D::SupportElements> move_bounds(m_highest_overhang_layer + 1);
|
||||||
profiler.stage_start(STAGE_GENERATE_CONTACT_NODES);
|
profiler.stage_start(STAGE_GENERATE_CONTACT_NODES);
|
||||||
#if USE_SUPPORT_3D
|
#if USE_SUPPORT_3D
|
||||||
m_object->print()->set_status(56, _L("Support: precalculate avoidance"));
|
m_object->print()->set_status(56, _u8L("Support: precalculate avoidance"));
|
||||||
|
|
||||||
Points bedpts = m_machine_border.contour.points;
|
Points bedpts = m_machine_border.contour.points;
|
||||||
BuildVolume build_volume{ Pointfs{ unscaled(bedpts[0]), unscaled(bedpts[1]),unscaled(bedpts[2]),unscaled(bedpts[3])}, m_print_config->printable_height };
|
BuildVolume build_volume{ Pointfs{ unscaled(bedpts[0]), unscaled(bedpts[1]),unscaled(bedpts[2]),unscaled(bedpts[3])}, m_print_config->printable_height };
|
||||||
|
@ -1904,7 +1917,7 @@ void TreeSupport::generate()
|
||||||
SupportGeneratorLayerStorage layer_storage;
|
SupportGeneratorLayerStorage layer_storage;
|
||||||
std::vector<Polygons> overhangs;
|
std::vector<Polygons> overhangs;
|
||||||
|
|
||||||
m_object->print()->set_status(57, _L("Support: generate contact points"));
|
m_object->print()->set_status(57, _u8L("Support: generate contact points"));
|
||||||
if (support_style != smsTreeHybrid) {
|
if (support_style != smsTreeHybrid) {
|
||||||
overhangs.resize(m_object->support_layer_count());
|
overhangs.resize(m_object->support_layer_count());
|
||||||
for (size_t i = 0; i < overhangs.size(); i++) {
|
for (size_t i = 0; i < overhangs.size(); i++) {
|
||||||
|
@ -1920,7 +1933,7 @@ void TreeSupport::generate()
|
||||||
|
|
||||||
//Drop nodes to lower layers.
|
//Drop nodes to lower layers.
|
||||||
profiler.stage_start(STAGE_DROP_DOWN_NODES);
|
profiler.stage_start(STAGE_DROP_DOWN_NODES);
|
||||||
m_object->print()->set_status(60, _L("Support: propagate branches"));
|
m_object->print()->set_status(60, _u8L("Support: propagate branches"));
|
||||||
drop_nodes(contact_nodes);
|
drop_nodes(contact_nodes);
|
||||||
profiler.stage_finish(STAGE_DROP_DOWN_NODES);
|
profiler.stage_finish(STAGE_DROP_DOWN_NODES);
|
||||||
|
|
||||||
|
@ -1928,14 +1941,14 @@ void TreeSupport::generate()
|
||||||
|
|
||||||
//Generate support areas.
|
//Generate support areas.
|
||||||
profiler.stage_start(STAGE_DRAW_CIRCLES);
|
profiler.stage_start(STAGE_DRAW_CIRCLES);
|
||||||
m_object->print()->set_status(65, _L("Support: draw polygons"));
|
m_object->print()->set_status(65, _u8L("Support: draw polygons"));
|
||||||
draw_circles(contact_nodes);
|
draw_circles(contact_nodes);
|
||||||
profiler.stage_finish(STAGE_DRAW_CIRCLES);
|
profiler.stage_finish(STAGE_DRAW_CIRCLES);
|
||||||
|
|
||||||
clear_contact_nodes(contact_nodes);
|
clear_contact_nodes(contact_nodes);
|
||||||
|
|
||||||
profiler.stage_start(STAGE_GENERATE_TOOLPATHS);
|
profiler.stage_start(STAGE_GENERATE_TOOLPATHS);
|
||||||
m_object->print()->set_status(69, _L("Support: generate toolpath"));
|
m_object->print()->set_status(69, _u8L("Support: generate toolpath"));
|
||||||
generate_toolpaths();
|
generate_toolpaths();
|
||||||
profiler.stage_finish(STAGE_GENERATE_TOOLPATHS);
|
profiler.stage_finish(STAGE_GENERATE_TOOLPATHS);
|
||||||
|
|
||||||
|
@ -2316,7 +2329,7 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_object->print()->set_status(65, (boost::format( _L("Support: generate polygons at layer %d")) % layer_nr).str());
|
m_object->print()->set_status(65, (boost::format( _u8L("Support: generate polygons at layer %d")) % layer_nr).str());
|
||||||
|
|
||||||
// join roof segments
|
// join roof segments
|
||||||
double contact_dist_scaled = scale_(0.5);// scale_(m_slicing_params.gap_support_object);
|
double contact_dist_scaled = scale_(0.5);// scale_(m_slicing_params.gap_support_object);
|
||||||
|
@ -2523,7 +2536,7 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no
|
||||||
std::map<const Polygon*, std::tuple<int, Point, Point>> holePropagationInfos;
|
std::map<const Polygon*, std::tuple<int, Point, Point>> holePropagationInfos;
|
||||||
for (int layer_nr = m_object->layer_count() - 1; layer_nr > 0; layer_nr--) {
|
for (int layer_nr = m_object->layer_count() - 1; layer_nr > 0; layer_nr--) {
|
||||||
if (print->canceled()) break;
|
if (print->canceled()) break;
|
||||||
m_object->print()->set_status(66, (boost::format(_L("Support: fix holes at layer %d")) % layer_nr).str());
|
m_object->print()->set_status(66, (boost::format(_u8L("Support: fix holes at layer %d")) % layer_nr).str());
|
||||||
|
|
||||||
const std::vector<Node*>& curr_layer_nodes = contact_nodes[layer_nr];
|
const std::vector<Node*>& curr_layer_nodes = contact_nodes[layer_nr];
|
||||||
SupportLayer* ts_layer = m_object->get_support_layer(layer_nr + m_raft_layers);
|
SupportLayer* ts_layer = m_object->get_support_layer(layer_nr + m_raft_layers);
|
||||||
|
@ -2620,8 +2633,7 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no
|
||||||
ExPolygons& roof_1st_layer = ts_layer->roof_1st_layer;
|
ExPolygons& roof_1st_layer = ts_layer->roof_1st_layer;
|
||||||
ExPolygons roofs = roof_areas; append(roofs, roof_1st_layer);
|
ExPolygons roofs = roof_areas; append(roofs, roof_1st_layer);
|
||||||
if (base_areas.empty() && roof_areas.empty() && roof_1st_layer.empty()) continue;
|
if (base_areas.empty() && roof_areas.empty() && roof_1st_layer.empty()) continue;
|
||||||
char fname[10]; sprintf(fname, "%d_%.2f", layer_nr, ts_layer->print_z);
|
draw_contours_and_nodes_to_svg(format("%d_%.2f", layer_nr, ts_layer->print_z), base_areas, roofs, ts_layer->lslices, {}, {}, "circles", {"base", "roof", "lslices"}, {"blue","red","black"});
|
||||||
draw_contours_and_nodes_to_svg("", base_areas, roofs, ts_layer->lslices, {}, {}, get_svg_filename(fname, "circles"), { "base", "roof", "lslices" }, { "blue","red","black" });
|
|
||||||
}
|
}
|
||||||
#endif // SUPPORT_TREE_DEBUG_TO_SVG
|
#endif // SUPPORT_TREE_DEBUG_TO_SVG
|
||||||
|
|
||||||
|
@ -2697,7 +2709,7 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
|
||||||
std::deque<std::pair<size_t, Node*>> unsupported_branch_leaves; // All nodes that are leaves on this layer that would result in unsupported ('mid-air') branches.
|
std::deque<std::pair<size_t, Node*>> unsupported_branch_leaves; // All nodes that are leaves on this layer that would result in unsupported ('mid-air') branches.
|
||||||
const Layer* ts_layer = m_object->get_support_layer(layer_nr);
|
const Layer* ts_layer = m_object->get_support_layer(layer_nr);
|
||||||
|
|
||||||
m_object->print()->set_status(60, (boost::format(_L("Support: propagate branches at layer %d")) % layer_nr).str());
|
m_object->print()->set_status(60, (boost::format(_u8L("Support: propagate branches at layer %d")) % layer_nr).str());
|
||||||
|
|
||||||
Polygons layer_contours = std::move(m_ts_data->get_contours_with_holes(layer_nr));
|
Polygons layer_contours = std::move(m_ts_data->get_contours_with_holes(layer_nr));
|
||||||
//std::unordered_map<Line, bool, LineHash>& mst_line_x_layer_contour_cache = m_mst_line_x_layer_contour_caches[layer_nr];
|
//std::unordered_map<Line, bool, LineHash>& mst_line_x_layer_contour_cache = m_mst_line_x_layer_contour_caches[layer_nr];
|
||||||
|
@ -3357,7 +3369,7 @@ std::vector<LayerHeightData> TreeSupport::plan_layer_heights(std::vector<std::ve
|
||||||
std::vector<LayerHeightData> layer_heights(contact_nodes.size());
|
std::vector<LayerHeightData> layer_heights(contact_nodes.size());
|
||||||
std::vector<int> bounds;
|
std::vector<int> bounds;
|
||||||
|
|
||||||
if (!USE_PLAN_LAYER_HEIGHTS || layer_height == max_layer_height || !m_support_params.independent_layer_height) {
|
if (layer_height == max_layer_height || !m_support_params.independent_layer_height) {
|
||||||
for (int layer_nr = 0; layer_nr < contact_nodes.size(); layer_nr++) {
|
for (int layer_nr = 0; layer_nr < contact_nodes.size(); layer_nr++) {
|
||||||
layer_heights[layer_nr] = {m_object->get_layer(layer_nr)->print_z, m_object->get_layer(layer_nr)->height, layer_nr > 0 ? size_t(layer_nr - 1) : 0};
|
layer_heights[layer_nr] = {m_object->get_layer(layer_nr)->print_z, m_object->get_layer(layer_nr)->height, layer_nr > 0 ? size_t(layer_nr - 1) : 0};
|
||||||
}
|
}
|
||||||
|
|
|
@ -617,11 +617,11 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
||||||
//toggle_field("support_closing_radius", have_support_material && support_style == smsSnug);
|
//toggle_field("support_closing_radius", have_support_material && support_style == smsSnug);
|
||||||
|
|
||||||
bool support_is_tree = config->opt_bool("enable_support") && is_tree(support_type);
|
bool support_is_tree = config->opt_bool("enable_support") && is_tree(support_type);
|
||||||
for (auto el : {"tree_support_branch_angle", "tree_support_wall_count", "tree_support_branch_distance", "tree_support_branch_diameter","tree_support_brim_width"})
|
for (auto el : {"tree_support_branch_angle", "tree_support_branch_distance", "tree_support_branch_diameter","tree_support_brim_width"})
|
||||||
toggle_field(el, support_is_tree);
|
toggle_field(el, support_is_tree);
|
||||||
|
|
||||||
// hide tree support settings when normal is selected
|
// hide tree support settings when normal is selected
|
||||||
for (auto el : {"tree_support_branch_angle", "tree_support_wall_count", "tree_support_branch_distance", "tree_support_branch_diameter", "max_bridge_length","tree_support_brim_width" })
|
for (auto el : {"tree_support_branch_angle", "tree_support_branch_distance", "tree_support_branch_diameter", "max_bridge_length","tree_support_brim_width" })
|
||||||
toggle_line(el, support_is_tree);
|
toggle_line(el, support_is_tree);
|
||||||
toggle_line("support_critical_regions_only", is_auto(support_type) && support_is_tree);
|
toggle_line("support_critical_regions_only", is_auto(support_type) && support_is_tree);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue