ENH: accurate top z distance for tree support

1. accurate top z distance for tree support
 Also fix a bug that bottom z and top z distances are misused.
    jira: STUDIO-3000, STUDIO-5990
    github: #1827
2. Change interface pattern to interlaced rectilinear when using
support material.
2. clean up tree support code

Change-Id: Icc8ce1b6844c841a6fbd1d623df707fdc8ed0f7b
(cherry picked from commit da7412a48dfb5767918ef125b9d0fb9718c03a61)
(cherry picked from commit 39ae64fc53abec794d740e36baaa13fd6fb35849)
This commit is contained in:
Arthur 2024-01-06 21:27:46 +08:00 committed by Noisyfox
parent de24d0ac2f
commit d0868d6711
8 changed files with 365 additions and 372 deletions

View file

@ -7315,11 +7315,11 @@ msgstr ""
msgid "" msgid ""
"When using support material for the support interface, We recommend the " "When using support material for the support interface, We recommend the "
"following settings:\n" "following settings:\n"
"0 top z distance, 0 interface spacing, concentric pattern and disable " "0 top z distance, 0 interface spacing, interlaced rectilinear pattern and disable "
"independent support layer height" "independent support layer height"
msgstr "" msgstr ""
"当使用支持界面的支持材料时,我们推荐以下设置:\n" "当使用支持界面的支持材料时,我们推荐以下设置:\n"
"0顶层z距离0接触层间距同心图案,并且禁用独立支撑层高" "0顶层z距离0接触层间距交叠直线图案,并且禁用独立支撑层高"
msgid "" msgid ""
"Enabling this option will modify the model's shape. If your print requires " "Enabling this option will modify the model's shape. If your print requires "

View file

@ -666,6 +666,10 @@ Slic3r::Polygons diff_clipped(const Slic3r::Polygons &subject, const Slic3r::Pol
{ return diff(subject, ClipperUtils::clip_clipper_polygons_with_subject_bbox(clip, get_extents(subject).inflated(SCALED_EPSILON)), do_safety_offset); } { return diff(subject, ClipperUtils::clip_clipper_polygons_with_subject_bbox(clip, get_extents(subject).inflated(SCALED_EPSILON)), do_safety_offset); }
Slic3r::ExPolygons diff_clipped(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset) Slic3r::ExPolygons diff_clipped(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset)
{ return diff_ex(subject, ClipperUtils::clip_clipper_polygons_with_subject_bbox(clip, get_extents(subject).inflated(SCALED_EPSILON)), do_safety_offset); } { return diff_ex(subject, ClipperUtils::clip_clipper_polygons_with_subject_bbox(clip, get_extents(subject).inflated(SCALED_EPSILON)), do_safety_offset); }
Slic3r::ExPolygons diff_clipped(const Slic3r::ExPolygons & subject, const Slic3r::ExPolygons & clip, ApplySafetyOffset do_safety_offset)
{
return diff_ex(subject, ClipperUtils::clip_clipper_polygons_with_subject_bbox(clip, get_extents(subject).inflated(SCALED_EPSILON)), do_safety_offset);
}
Slic3r::Polygons diff(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, ApplySafetyOffset do_safety_offset) Slic3r::Polygons diff(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, ApplySafetyOffset do_safety_offset)
{ return _clipper(ClipperLib::ctDifference, ClipperUtils::PolygonsProvider(subject), ClipperUtils::ExPolygonsProvider(clip), do_safety_offset); } { return _clipper(ClipperLib::ctDifference, ClipperUtils::PolygonsProvider(subject), ClipperUtils::ExPolygonsProvider(clip), do_safety_offset); }
Slic3r::Polygons diff(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset) Slic3r::Polygons diff(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset)

View file

@ -434,6 +434,7 @@ Slic3r::Polygons diff(const Slic3r::Polygons &subject, const Slic3r::ExPolygon
// To be used with complex clipping polygons, where majority of the clipping polygons are outside of the source polygon. // To be used with complex clipping polygons, where majority of the clipping polygons are outside of the source polygon.
Slic3r::Polygons diff_clipped(const Slic3r::Polygons &src, const Slic3r::Polygons &clipping, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No); Slic3r::Polygons diff_clipped(const Slic3r::Polygons &src, const Slic3r::Polygons &clipping, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
Slic3r::ExPolygons diff_clipped(const Slic3r::ExPolygons &src, const Slic3r::Polygons &clipping, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No); Slic3r::ExPolygons diff_clipped(const Slic3r::ExPolygons &src, const Slic3r::Polygons &clipping, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
Slic3r::ExPolygons diff_clipped(const Slic3r::ExPolygons &src, const Slic3r::ExPolygons &clipping, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
Slic3r::Polygons diff(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No); Slic3r::Polygons diff(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
Slic3r::Polygons diff(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No); Slic3r::Polygons diff(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
Slic3r::Polygons diff(const Slic3r::Surfaces &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No); Slic3r::Polygons diff(const Slic3r::Surfaces &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);

View file

@ -317,7 +317,7 @@ protected:
bool need_extra_wall = false; bool need_extra_wall = false;
AreaGroup(ExPolygon *a, int t, coordf_t d) : area(a), type(t), dist_to_top(d) {} AreaGroup(ExPolygon *a, int t, coordf_t d) : area(a), type(t), dist_to_top(d) {}
}; };
enum OverhangType { Detected = 0, Enforced }; enum OverhangType { Detected = 0, Enforced, SharpTail };
std::vector<AreaGroup> area_groups; std::vector<AreaGroup> area_groups;
std::map<const ExPolygon *, OverhangType> overhang_types; std::map<const ExPolygon *, OverhangType> overhang_types;
}; };

File diff suppressed because it is too large Load diff

View file

@ -31,14 +31,8 @@ struct LayerHeightData
size_t next_layer_nr = 0; size_t next_layer_nr = 0;
LayerHeightData() = default; LayerHeightData() = default;
LayerHeightData(coordf_t z, coordf_t h, size_t next_layer) : print_z(z), height(h), next_layer_nr(next_layer) {} LayerHeightData(coordf_t z, coordf_t h, size_t next_layer) : print_z(z), height(h), next_layer_nr(next_layer) {}
}; coordf_t bottom_z() {
return print_z - height;
struct TreeNode {
Vec3f pos;
std::vector<int> children; // index of children in the storing vector
std::vector<int> parents; // index of parents in the storing vector
TreeNode(Point pt, float z) {
pos = { float(unscale_(pt.x())),float(unscale_(pt.y())),z };
} }
}; };
@ -57,40 +51,45 @@ struct SupportNode
static constexpr SupportNode* NO_PARENT = nullptr; static constexpr SupportNode* NO_PARENT = nullptr;
SupportNode() SupportNode()
: distance_to_top(0) : distance_to_top(0)
, position(Point(0, 0)) , position(Point(0, 0))
, obj_layer_nr(0) , obj_layer_nr(0)
, support_roof_layers_below(0) , support_roof_layers_below(0)
, to_buildplate(true) , to_buildplate(true)
, parent(nullptr) , parent(nullptr)
, print_z(0.0) , print_z(0.0)
, height(0.0) , height(0.0)
{} {}
// when dist_mm_to_top_==0, new node's dist_mm_to_top=parent->dist_mm_to_top + parent->height; // when dist_mm_to_top_==0, new node's dist_mm_to_top=parent->dist_mm_to_top + parent->height;
SupportNode(const Point position, const int distance_to_top, const int obj_layer_nr, const int support_roof_layers_below, const bool to_buildplate, SupportNode* parent, SupportNode(const Point position, const int distance_to_top, const int obj_layer_nr, const int support_roof_layers_below, const bool to_buildplate, SupportNode* parent,
coordf_t print_z_, coordf_t height_, coordf_t dist_mm_to_top_=0) coordf_t print_z_, coordf_t height_, coordf_t dist_mm_to_top_ = 0, coordf_t radius_ = 0)
: distance_to_top(distance_to_top) : distance_to_top(distance_to_top)
, position(position) , position(position)
, obj_layer_nr(obj_layer_nr) , obj_layer_nr(obj_layer_nr)
, support_roof_layers_below(support_roof_layers_below) , support_roof_layers_below(support_roof_layers_below)
, to_buildplate(to_buildplate) , to_buildplate(to_buildplate)
, parent(parent) , parent(parent)
, print_z(print_z_) , print_z(print_z_)
, height(height_) , height(height_)
, dist_mm_to_top(dist_mm_to_top_) , dist_mm_to_top(dist_mm_to_top_)
, radius(radius_)
{ {
if (parent) { if (parent) {
parents.push_back(parent); parents.push_back(parent);
type = parent->type; type = parent->type;
overhang = parent->overhang; overhang = parent->overhang;
if (dist_mm_to_top==0) if (dist_mm_to_top == 0)
dist_mm_to_top = parent->dist_mm_to_top + parent->height; dist_mm_to_top = parent->dist_mm_to_top + parent->height;
if (radius == 0)
radius = parent->radius + (dist_mm_to_top - parent->dist_mm_to_top) * diameter_angle_scale_factor;
parent->child = this; parent->child = this;
for (auto& neighbor : parent->merged_neighbours) { for (auto& neighbor : parent->merged_neighbours) {
neighbor->child = this; neighbor->child = this;
parents.push_back(neighbor); parents.push_back(neighbor);
} }
is_sharp_tail = parent->is_sharp_tail;
skin_direction = parent->skin_direction;
} }
} }
@ -109,18 +108,23 @@ struct SupportNode
int distance_to_top; int distance_to_top;
coordf_t dist_mm_to_top = 0; // dist to bottom contact in mm coordf_t dist_mm_to_top = 0; // dist to bottom contact in mm
// all nodes will have same diameter_angle_scale_factor because it's defined by user
static double diameter_angle_scale_factor;
/*! /*!
* \brief The position of this node on the layer. * \brief The position of this node on the layer.
*/ */
Point position; Point position;
Point movement; // movement towards neighbor center or outline Point movement; // movement towards neighbor center or outline
mutable double radius = 0.0; mutable double radius = 0.0;
mutable double max_move_dist = 0.0; mutable double max_move_dist = 0.0;
TreeNodeType type = eCircle; TreeNodeType type = eCircle;
bool is_corner = false; bool is_corner = false;
bool is_processed = false; bool is_processed = false;
bool need_extra_wall = false; bool need_extra_wall = false;
ExPolygon overhang; // when type==ePolygon, set this value to get original overhang area bool is_sharp_tail = false;
bool valid = true;
ExPolygon overhang; // when type==ePolygon, set this value to get original overhang area
/*! /*!
* \brief The direction of the skin lines above the tip of the branch. * \brief The direction of the skin lines above the tip of the branch.
@ -128,7 +132,7 @@ struct SupportNode
* This determines in which direction we should reduce the width of the * This determines in which direction we should reduce the width of the
* branch. * branch.
*/ */
bool skin_direction; Point skin_direction;
/*! /*!
* \brief The number of support roof layers below this one. * \brief The number of support roof layers below this one.
@ -199,6 +203,9 @@ public:
* \param collision_resolution * \param collision_resolution
*/ */
TreeSupportData(const PrintObject& object, coordf_t max_move, coordf_t radius_sample_resolution, coordf_t collision_resolution); TreeSupportData(const PrintObject& object, coordf_t max_move, coordf_t radius_sample_resolution, coordf_t collision_resolution);
~TreeSupportData() {
clear_nodes();
}
TreeSupportData(TreeSupportData&&) = default; TreeSupportData(TreeSupportData&&) = default;
TreeSupportData& operator=(TreeSupportData&&) = default; TreeSupportData& operator=(TreeSupportData&&) = default;
@ -237,9 +244,13 @@ public:
Polygons get_contours(size_t layer_nr) const; Polygons get_contours(size_t layer_nr) const;
Polygons get_contours_with_holes(size_t layer_nr) const; Polygons get_contours_with_holes(size_t layer_nr) const;
SupportNode* create_node(const Point position, const int distance_to_top, const int obj_layer_nr, const int support_roof_layers_below, const bool to_buildplate, SupportNode* parent,
coordf_t print_z_, coordf_t height_, coordf_t dist_mm_to_top_ = 0, coordf_t radius_ = 0);
void clear_nodes();
void remove_invalid_nodes();
std::vector<LayerHeightData> layer_heights; std::vector<LayerHeightData> layer_heights;
std::vector<TreeNode> tree_nodes; std::vector<SupportNode*> contact_nodes;
private: private:
/*! /*!
@ -285,6 +296,7 @@ private:
*/ */
const ExPolygons& calculate_avoidance(const RadiusLayerPair& key) const; const ExPolygons& calculate_avoidance(const RadiusLayerPair& key) const;
tbb::spin_mutex m_mutex;
public: public:
bool is_slim = false; bool is_slim = false;

View file

@ -6,6 +6,7 @@
#include <ctime> #include <ctime>
#include <cstdarg> #include <cstdarg>
#include <stdio.h> #include <stdio.h>
#include <filesystem>
#include "format.hpp" #include "format.hpp"
#include "Platform.hpp" #include "Platform.hpp"
@ -298,12 +299,13 @@ static std::atomic<bool> debug_out_path_called(false);
std::string debug_out_path(const char *name, ...) std::string debug_out_path(const char *name, ...)
{ {
static constexpr const char *SLIC3R_DEBUG_OUT_PATH_PREFIX = "out/"; //static constexpr const char *SLIC3R_DEBUG_OUT_PATH_PREFIX = "out/";
auto svg_folder = boost::filesystem::path(g_data_dir) / "SVG/";
if (! debug_out_path_called.exchange(true)) { if (! debug_out_path_called.exchange(true)) {
std::string path = boost::filesystem::system_complete(SLIC3R_DEBUG_OUT_PATH_PREFIX).string(); if (!boost::filesystem::exists(svg_folder)) {
if (!boost::filesystem::exists(path)) { boost::filesystem::create_directory(svg_folder);
boost::filesystem::create_directory(path);
} }
std::string path = boost::filesystem::system_complete(svg_folder).string();
printf("Debugging output files will be written to %s\n", path.c_str()); printf("Debugging output files will be written to %s\n", path.c_str());
} }
char buffer[2048]; char buffer[2048];
@ -311,7 +313,13 @@ std::string debug_out_path(const char *name, ...)
va_start(args, name); va_start(args, name);
std::vsprintf(buffer, name, args); std::vsprintf(buffer, name, args);
va_end(args); va_end(args);
return std::string(SLIC3R_DEBUG_OUT_PATH_PREFIX) + std::string(buffer);
std::string buf(buffer);
if (size_t pos = buf.find_first_of('/'); pos != std::string::npos) {
std::string sub_dir = buf.substr(0, pos);
std::filesystem::create_directory(svg_folder.string() + sub_dir);
}
return svg_folder.string() + std::string(buffer);
} }
namespace logging = boost::log; namespace logging = boost::log;

View file

@ -1537,9 +1537,9 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
if (opt_key == "support_interface_filament") { if (opt_key == "support_interface_filament") {
int interface_filament_id = m_config->opt_int("support_interface_filament") - 1; // the displayed id is based from 1, while internal id is based from 0 int interface_filament_id = m_config->opt_int("support_interface_filament") - 1; // the displayed id is based from 1, while internal id is based from 0
if (is_support_filament(interface_filament_id) && !(m_config->opt_float("support_top_z_distance") == 0 && m_config->opt_float("support_interface_spacing") == 0 && if (is_support_filament(interface_filament_id) && !(m_config->opt_float("support_top_z_distance") == 0 && m_config->opt_float("support_interface_spacing") == 0 &&
m_config->opt_enum<SupportMaterialInterfacePattern>("support_interface_pattern") == SupportMaterialInterfacePattern::smipConcentric)) { m_config->opt_enum<SupportMaterialInterfacePattern>("support_interface_pattern") == SupportMaterialInterfacePattern::smipRectilinearInterlaced)) {
wxString msg_text = _L("When using support material for the support interface, We recommend the following settings:\n" wxString msg_text = _L("When using support material for the support interface, We recommend the following settings:\n"
"0 top z distance, 0 interface spacing, concentric pattern and disable independent support layer height"); "0 top z distance, 0 interface spacing, interlaced rectilinear pattern and disable independent support layer height");
msg_text += "\n\n" + _L("Change these settings automatically? \n" msg_text += "\n\n" + _L("Change these settings automatically? \n"
"Yes - Change these settings automatically\n" "Yes - Change these settings automatically\n"
"No - Do not change these settings for me"); "No - Do not change these settings for me");
@ -1548,7 +1548,7 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
if (dialog.ShowModal() == wxID_YES) { if (dialog.ShowModal() == wxID_YES) {
new_conf.set_key_value("support_top_z_distance", new ConfigOptionFloat(0)); new_conf.set_key_value("support_top_z_distance", new ConfigOptionFloat(0));
new_conf.set_key_value("support_interface_spacing", new ConfigOptionFloat(0)); new_conf.set_key_value("support_interface_spacing", new ConfigOptionFloat(0));
new_conf.set_key_value("support_interface_pattern", new ConfigOptionEnum<SupportMaterialInterfacePattern>(SupportMaterialInterfacePattern::smipConcentric)); new_conf.set_key_value("support_interface_pattern", new ConfigOptionEnum<SupportMaterialInterfacePattern>(SupportMaterialInterfacePattern::smipRectilinearInterlaced));
new_conf.set_key_value("independent_support_layer_height", new ConfigOptionBool(false)); new_conf.set_key_value("independent_support_layer_height", new ConfigOptionBool(false));
m_config_manipulation.apply(m_config, &new_conf); m_config_manipulation.apply(m_config, &new_conf);
} }