mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-07 23:17:35 -06:00
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:
parent
de24d0ac2f
commit
d0868d6711
8 changed files with 365 additions and 372 deletions
|
@ -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 "
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue