mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-10 08:17:51 -06:00
WIP: Port latest support code from BBS (#8212)
This includes the latest changes from BBS, including vertical support painting. Huge PR, lots of tests are needed.
This commit is contained in:
commit
41584cfae3
35 changed files with 2253 additions and 4614 deletions
|
@ -7351,11 +7351,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 "
|
||||||
|
|
|
@ -310,16 +310,16 @@ set(lisbslic3r_sources
|
||||||
Support/SupportLayer.hpp
|
Support/SupportLayer.hpp
|
||||||
Support/SupportMaterial.cpp
|
Support/SupportMaterial.cpp
|
||||||
Support/SupportMaterial.hpp
|
Support/SupportMaterial.hpp
|
||||||
Support/SupportParameters.hpp
|
|
||||||
Support/SupportSpotsGenerator.cpp
|
Support/SupportSpotsGenerator.cpp
|
||||||
Support/SupportSpotsGenerator.hpp
|
Support/SupportSpotsGenerator.hpp
|
||||||
Support/TreeSupport.hpp
|
Support/TreeSupport.hpp
|
||||||
Support/TreeSupport.cpp
|
Support/TreeSupport.cpp
|
||||||
Support/TreeSupport3D.cpp
|
|
||||||
Support/TreeSupport3D.hpp
|
Support/TreeSupport3D.hpp
|
||||||
Support/TreeSupportCommon.hpp
|
Support/TreeSupport3D.cpp
|
||||||
Support/TreeModelVolumes.cpp
|
|
||||||
Support/TreeModelVolumes.hpp
|
Support/TreeModelVolumes.hpp
|
||||||
|
Support/TreeModelVolumes.cpp
|
||||||
|
Support/TreeSupportCommon.hpp
|
||||||
|
Support/SupportParameters.hpp
|
||||||
PrincipalComponents2D.cpp
|
PrincipalComponents2D.cpp
|
||||||
PrincipalComponents2D.hpp
|
PrincipalComponents2D.hpp
|
||||||
MinimumSpanningTree.hpp
|
MinimumSpanningTree.hpp
|
||||||
|
|
|
@ -664,6 +664,12 @@ Slic3r::Polygons diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &c
|
||||||
{ return _clipper(ClipperLib::ctDifference, ClipperUtils::PolygonsProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
|
{ return _clipper(ClipperLib::ctDifference, ClipperUtils::PolygonsProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
|
||||||
Slic3r::Polygons diff_clipped(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset)
|
Slic3r::Polygons diff_clipped(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset)
|
||||||
{ 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)
|
||||||
|
{ 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)
|
||||||
|
|
|
@ -433,6 +433,8 @@ Slic3r::Polygons diff(const Slic3r::Polygons &subject, const Slic3r::ExPolygon
|
||||||
// Optimized version clipping the "clipping" polygon using clip_clipper_polygon_with_subject_bbox().
|
// Optimized version clipping the "clipping" polygon using clip_clipper_polygon_with_subject_bbox().
|
||||||
// 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::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);
|
||||||
|
|
|
@ -57,7 +57,7 @@ Fill* Fill::new_from_type(const InfillPattern type)
|
||||||
case ipOctagramSpiral: return new FillOctagramSpiral();
|
case ipOctagramSpiral: return new FillOctagramSpiral();
|
||||||
case ipAdaptiveCubic: return new FillAdaptive::Filler();
|
case ipAdaptiveCubic: return new FillAdaptive::Filler();
|
||||||
case ipSupportCubic: return new FillAdaptive::Filler();
|
case ipSupportCubic: return new FillAdaptive::Filler();
|
||||||
case ipSupportBase: return new FillSupportBase();
|
case ipSupportBase: return new FillSupportBase(); // simply line fill
|
||||||
case ipLightning: return new FillLightning::Filler();
|
case ipLightning: return new FillLightning::Filler();
|
||||||
// BBS: for internal solid infill only
|
// BBS: for internal solid infill only
|
||||||
case ipConcentricInternal: return new FillConcentricInternal();
|
case ipConcentricInternal: return new FillConcentricInternal();
|
||||||
|
|
|
@ -1202,14 +1202,23 @@ std::vector<GCode::LayerToPrint> GCode::collect_layers_to_print(const PrintObjec
|
||||||
// Allow empty support layers, as the support generator may produce no extrusions for non-empty support regions.
|
// Allow empty support layers, as the support generator may produce no extrusions for non-empty support regions.
|
||||||
|| (layer_to_print.support_layer /* && layer_to_print.support_layer->has_extrusions() */)) {
|
|| (layer_to_print.support_layer /* && layer_to_print.support_layer->has_extrusions() */)) {
|
||||||
double top_cd = object.config().support_top_z_distance;
|
double top_cd = object.config().support_top_z_distance;
|
||||||
double bottom_cd = object.config().support_bottom_z_distance;
|
double bottom_cd = object.config().support_bottom_z_distance == 0. ? top_cd : object.config().support_bottom_z_distance;
|
||||||
|
//if (!object.print()->config().independent_support_layer_height)
|
||||||
|
{ // the actual support gap may be larger than the configured one due to rounding to layer height for organic support, regardless of independent support layer height
|
||||||
|
top_cd = std::ceil(top_cd / object.config().layer_height) * object.config().layer_height;
|
||||||
|
bottom_cd = std::ceil(bottom_cd / object.config().layer_height) * object.config().layer_height;
|
||||||
|
}
|
||||||
double extra_gap = (layer_to_print.support_layer ? bottom_cd : top_cd);
|
double extra_gap = (layer_to_print.support_layer ? bottom_cd : top_cd);
|
||||||
|
|
||||||
// raft contact distance should not trigger any warning
|
// raft contact distance should not trigger any warning
|
||||||
if(last_extrusion_layer && last_extrusion_layer->support_layer)
|
if (last_extrusion_layer && last_extrusion_layer->support_layer) {
|
||||||
|
double raft_gap = object.config().raft_contact_distance.value;
|
||||||
|
//if (!object.print()->config().independent_support_layer_height)
|
||||||
|
{
|
||||||
|
raft_gap = std::ceil(raft_gap / object.config().layer_height) * object.config().layer_height;
|
||||||
|
}
|
||||||
extra_gap = std::max(extra_gap, object.config().raft_contact_distance.value);
|
extra_gap = std::max(extra_gap, object.config().raft_contact_distance.value);
|
||||||
|
}
|
||||||
double maximal_print_z = (last_extrusion_layer ? last_extrusion_layer->print_z() : 0.)
|
double maximal_print_z = (last_extrusion_layer ? last_extrusion_layer->print_z() : 0.)
|
||||||
+ layer_to_print.layer()->height
|
+ layer_to_print.layer()->height
|
||||||
+ std::max(0., extra_gap);
|
+ std::max(0., extra_gap);
|
||||||
|
|
|
@ -139,7 +139,7 @@ public:
|
||||||
// BBS
|
// BBS
|
||||||
mutable ExPolygons sharp_tails;
|
mutable ExPolygons sharp_tails;
|
||||||
mutable ExPolygons cantilevers;
|
mutable ExPolygons cantilevers;
|
||||||
mutable std::map<const ExPolygon*, float> sharp_tails_height;
|
mutable std::vector<float> sharp_tails_height;
|
||||||
|
|
||||||
// Collection of expolygons generated by slicing the possibly multiple meshes of the source geometry
|
// Collection of expolygons generated by slicing the possibly multiple meshes of the source geometry
|
||||||
// (with possibly differing extruder ID and slicing parameters) and merged.
|
// (with possibly differing extruder ID and slicing parameters) and merged.
|
||||||
|
@ -150,6 +150,7 @@ public:
|
||||||
// These lslices are also used to detect overhangs and overlaps between successive layers, therefore it is important
|
// These lslices are also used to detect overhangs and overlaps between successive layers, therefore it is important
|
||||||
// that the 1st lslice is not compensated by the Elephant foot compensation algorithm.
|
// that the 1st lslice is not compensated by the Elephant foot compensation algorithm.
|
||||||
ExPolygons lslices;
|
ExPolygons lslices;
|
||||||
|
ExPolygons lslices_extrudable; // BBS: the extrudable part of lslices used for tree support
|
||||||
std::vector<BoundingBox> lslices_bboxes;
|
std::vector<BoundingBox> lslices_bboxes;
|
||||||
|
|
||||||
// BBS
|
// BBS
|
||||||
|
@ -278,7 +279,6 @@ public:
|
||||||
|
|
||||||
// for tree supports
|
// for tree supports
|
||||||
ExPolygons base_areas;
|
ExPolygons base_areas;
|
||||||
ExPolygons overhang_areas;
|
|
||||||
|
|
||||||
|
|
||||||
// Is there any valid extrusion assigned to this LayerRegion?
|
// Is there any valid extrusion assigned to this LayerRegion?
|
||||||
|
@ -311,14 +311,13 @@ protected:
|
||||||
{
|
{
|
||||||
ExPolygon *area;
|
ExPolygon *area;
|
||||||
int type;
|
int type;
|
||||||
|
int interface_id = 0;
|
||||||
coordf_t dist_to_top; // mm dist to top
|
coordf_t dist_to_top; // mm dist to top
|
||||||
bool need_infill = false;
|
bool need_infill = false;
|
||||||
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 };
|
|
||||||
std::vector<AreaGroup> area_groups;
|
std::vector<AreaGroup> area_groups;
|
||||||
std::map<const ExPolygon *, OverhangType> overhang_types;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename LayerContainer>
|
template<typename LayerContainer>
|
||||||
|
|
|
@ -1363,7 +1363,7 @@ static inline std::vector<std::vector<ExPolygons>> mmu_segmentation_top_and_bott
|
||||||
if (!zs.empty() && is_volume_sinking(painted, volume_trafo)) {
|
if (!zs.empty() && is_volume_sinking(painted, volume_trafo)) {
|
||||||
std::vector<float> zs_sinking = {0.f};
|
std::vector<float> zs_sinking = {0.f};
|
||||||
Slic3r::append(zs_sinking, zs);
|
Slic3r::append(zs_sinking, zs);
|
||||||
slice_mesh_slabs(painted, zs_sinking, volume_trafo, max_top_layers > 0 ? &top : nullptr, max_bottom_layers > 0 ? &bottom : nullptr, throw_on_cancel_callback);
|
slice_mesh_slabs(painted, zs_sinking, volume_trafo, max_top_layers > 0 ? &top : nullptr, max_bottom_layers > 0 ? &bottom : nullptr, nullptr, throw_on_cancel_callback);
|
||||||
|
|
||||||
MeshSlicingParams slicing_params;
|
MeshSlicingParams slicing_params;
|
||||||
slicing_params.trafo = volume_trafo;
|
slicing_params.trafo = volume_trafo;
|
||||||
|
@ -1374,7 +1374,7 @@ static inline std::vector<std::vector<ExPolygons>> mmu_segmentation_top_and_bott
|
||||||
|
|
||||||
bottom[0] = union_(bottom[0], bottom_slice);
|
bottom[0] = union_(bottom[0], bottom_slice);
|
||||||
} else
|
} else
|
||||||
slice_mesh_slabs(painted, zs, volume_trafo, max_top_layers > 0 ? &top : nullptr, max_bottom_layers > 0 ? &bottom : nullptr, throw_on_cancel_callback);
|
slice_mesh_slabs(painted, zs, volume_trafo, max_top_layers > 0 ? &top : nullptr, max_bottom_layers > 0 ? &bottom : nullptr, nullptr, throw_on_cancel_callback);
|
||||||
auto merge = [](std::vector<Polygons> &&src, std::vector<Polygons> &dst) {
|
auto merge = [](std::vector<Polygons> &&src, std::vector<Polygons> &dst) {
|
||||||
auto it_src = find_if(src.begin(), src.end(), [](const Polygons &p){ return ! p.empty(); });
|
auto it_src = find_if(src.begin(), src.end(), [](const Polygons &p){ return ! p.empty(); });
|
||||||
if (it_src != src.end()) {
|
if (it_src != src.end()) {
|
||||||
|
|
|
@ -794,7 +794,7 @@ static std::vector<std::string> s_Preset_print_options {
|
||||||
"fuzzy_skin", "fuzzy_skin_thickness", "fuzzy_skin_point_distance", "fuzzy_skin_first_layer", "fuzzy_skin_noise_type", "fuzzy_skin_scale", "fuzzy_skin_octaves", "fuzzy_skin_persistence",
|
"fuzzy_skin", "fuzzy_skin_thickness", "fuzzy_skin_point_distance", "fuzzy_skin_first_layer", "fuzzy_skin_noise_type", "fuzzy_skin_scale", "fuzzy_skin_octaves", "fuzzy_skin_persistence",
|
||||||
"max_volumetric_extrusion_rate_slope", "max_volumetric_extrusion_rate_slope_segment_length","extrusion_rate_smoothing_external_perimeter_only",
|
"max_volumetric_extrusion_rate_slope", "max_volumetric_extrusion_rate_slope_segment_length","extrusion_rate_smoothing_external_perimeter_only",
|
||||||
"inner_wall_speed", "outer_wall_speed", "sparse_infill_speed", "internal_solid_infill_speed",
|
"inner_wall_speed", "outer_wall_speed", "sparse_infill_speed", "internal_solid_infill_speed",
|
||||||
"top_surface_speed", "support_speed", "support_object_xy_distance", "support_interface_speed",
|
"top_surface_speed", "support_speed", "support_object_xy_distance", "support_object_first_layer_gap", "support_interface_speed",
|
||||||
"bridge_speed", "internal_bridge_speed", "gap_infill_speed", "travel_speed", "travel_speed_z", "initial_layer_speed",
|
"bridge_speed", "internal_bridge_speed", "gap_infill_speed", "travel_speed", "travel_speed_z", "initial_layer_speed",
|
||||||
"outer_wall_acceleration", "initial_layer_acceleration", "top_surface_acceleration", "default_acceleration", "skirt_type", "skirt_loops", "skirt_speed","min_skirt_length", "skirt_distance", "skirt_start_angle", "skirt_height", "draft_shield",
|
"outer_wall_acceleration", "initial_layer_acceleration", "top_surface_acceleration", "default_acceleration", "skirt_type", "skirt_loops", "skirt_speed","min_skirt_length", "skirt_distance", "skirt_start_angle", "skirt_height", "draft_shield",
|
||||||
"brim_width", "brim_object_gap", "brim_type", "brim_ears_max_angle", "brim_ears_detection_length", "enable_support", "support_type", "support_threshold_angle", "support_threshold_overlap","enforce_support_layers",
|
"brim_width", "brim_object_gap", "brim_type", "brim_ears_max_angle", "brim_ears_detection_length", "enable_support", "support_type", "support_threshold_angle", "support_threshold_overlap","enforce_support_layers",
|
||||||
|
@ -814,7 +814,7 @@ static std::vector<std::string> s_Preset_print_options {
|
||||||
"wipe_tower_no_sparse_layers", "compatible_printers", "compatible_printers_condition", "inherits",
|
"wipe_tower_no_sparse_layers", "compatible_printers", "compatible_printers_condition", "inherits",
|
||||||
"flush_into_infill", "flush_into_objects", "flush_into_support",
|
"flush_into_infill", "flush_into_objects", "flush_into_support",
|
||||||
"tree_support_branch_angle", "tree_support_angle_slow", "tree_support_wall_count", "tree_support_top_rate", "tree_support_branch_distance", "tree_support_tip_diameter",
|
"tree_support_branch_angle", "tree_support_angle_slow", "tree_support_wall_count", "tree_support_top_rate", "tree_support_branch_distance", "tree_support_tip_diameter",
|
||||||
"tree_support_branch_diameter", "tree_support_branch_diameter_angle", "tree_support_branch_diameter_double_wall",
|
"tree_support_branch_diameter", "tree_support_branch_diameter_angle",
|
||||||
"detect_narrow_internal_solid_infill",
|
"detect_narrow_internal_solid_infill",
|
||||||
"gcode_add_line_number", "enable_arc_fitting", "precise_z_height", "infill_combination","infill_combination_max_layer_height", /*"adaptive_layer_height",*/
|
"gcode_add_line_number", "enable_arc_fitting", "precise_z_height", "infill_combination","infill_combination_max_layer_height", /*"adaptive_layer_height",*/
|
||||||
"support_bottom_interface_spacing", "enable_overhang_speed", "slowdown_for_curled_perimeters", "overhang_1_4_speed", "overhang_2_4_speed", "overhang_3_4_speed", "overhang_4_4_speed",
|
"support_bottom_interface_spacing", "enable_overhang_speed", "slowdown_for_curled_perimeters", "overhang_1_4_speed", "overhang_2_4_speed", "overhang_3_4_speed", "overhang_4_4_speed",
|
||||||
|
|
|
@ -1167,7 +1167,7 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
|
||||||
// Custom layering is not allowed for tree supports as of now.
|
// Custom layering is not allowed for tree supports as of now.
|
||||||
for (size_t print_object_idx = 0; print_object_idx < m_objects.size(); ++ print_object_idx)
|
for (size_t print_object_idx = 0; print_object_idx < m_objects.size(); ++ print_object_idx)
|
||||||
if (const PrintObject &print_object = *m_objects[print_object_idx];
|
if (const PrintObject &print_object = *m_objects[print_object_idx];
|
||||||
print_object.has_support_material() && is_tree(print_object.config().support_type.value) && (print_object.config().support_style.value == smsOrganic ||
|
print_object.has_support_material() && is_tree(print_object.config().support_type.value) && (print_object.config().support_style.value == smsTreeOrganic ||
|
||||||
// Orca: use organic as default
|
// Orca: use organic as default
|
||||||
print_object.config().support_style.value == smsDefault) &&
|
print_object.config().support_style.value == smsDefault) &&
|
||||||
print_object.model_object()->has_custom_layering()) {
|
print_object.model_object()->has_custom_layering()) {
|
||||||
|
@ -1340,7 +1340,7 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
|
||||||
|
|
||||||
// Prusa: Fixing crashes with invalid tip diameter or branch diameter
|
// Prusa: Fixing crashes with invalid tip diameter or branch diameter
|
||||||
// https://github.com/prusa3d/PrusaSlicer/commit/96b3ae85013ac363cd1c3e98ec6b7938aeacf46d
|
// https://github.com/prusa3d/PrusaSlicer/commit/96b3ae85013ac363cd1c3e98ec6b7938aeacf46d
|
||||||
if (is_tree(object->config().support_type.value) && (object->config().support_style == smsOrganic ||
|
if (is_tree(object->config().support_type.value) && (object->config().support_style == smsTreeOrganic ||
|
||||||
// Orca: use organic as default
|
// Orca: use organic as default
|
||||||
object->config().support_style == smsDefault)) {
|
object->config().support_style == smsDefault)) {
|
||||||
float extrusion_width = std::min(
|
float extrusion_width = std::min(
|
||||||
|
|
|
@ -385,7 +385,7 @@ public:
|
||||||
|
|
||||||
size_t support_layer_count() const { return m_support_layers.size(); }
|
size_t support_layer_count() const { return m_support_layers.size(); }
|
||||||
void clear_support_layers();
|
void clear_support_layers();
|
||||||
SupportLayer* get_support_layer(int idx) { return m_support_layers[idx]; }
|
SupportLayer* get_support_layer(int idx) { return idx<m_support_layers.size()? m_support_layers[idx]:nullptr; }
|
||||||
const SupportLayer* get_support_layer_at_printz(coordf_t print_z, coordf_t epsilon) const;
|
const SupportLayer* get_support_layer_at_printz(coordf_t print_z, coordf_t epsilon) const;
|
||||||
SupportLayer* get_support_layer_at_printz(coordf_t print_z, coordf_t epsilon);
|
SupportLayer* get_support_layer_at_printz(coordf_t print_z, coordf_t epsilon);
|
||||||
SupportLayer* add_support_layer(int id, int interface_id, coordf_t height, coordf_t print_z);
|
SupportLayer* add_support_layer(int id, int interface_id, coordf_t height, coordf_t print_z);
|
||||||
|
@ -427,7 +427,7 @@ public:
|
||||||
std::vector<Polygons> slice_support_enforcers() const { return this->slice_support_volumes(ModelVolumeType::SUPPORT_ENFORCER); }
|
std::vector<Polygons> slice_support_enforcers() const { return this->slice_support_volumes(ModelVolumeType::SUPPORT_ENFORCER); }
|
||||||
|
|
||||||
// Helpers to project custom facets on slices
|
// Helpers to project custom facets on slices
|
||||||
void project_and_append_custom_facets(bool seam, EnforcerBlockerType type, std::vector<Polygons>& expolys) const;
|
void project_and_append_custom_facets(bool seam, EnforcerBlockerType type, std::vector<Polygons>& expolys, std::vector<std::pair<Vec3f,Vec3f>>* vertical_points=nullptr) const;
|
||||||
|
|
||||||
//BBS
|
//BBS
|
||||||
BoundingBox get_first_layer_bbox(float& area, float& layer_height, std::string& name);
|
BoundingBox get_first_layer_bbox(float& area, float& layer_height, std::string& name);
|
||||||
|
|
|
@ -232,7 +232,7 @@ static t_config_enum_values s_keys_map_SupportMaterialStyle {
|
||||||
{ "tree_slim", smsTreeSlim },
|
{ "tree_slim", smsTreeSlim },
|
||||||
{ "tree_strong", smsTreeStrong },
|
{ "tree_strong", smsTreeStrong },
|
||||||
{ "tree_hybrid", smsTreeHybrid },
|
{ "tree_hybrid", smsTreeHybrid },
|
||||||
{ "organic", smsOrganic }
|
{ "organic", smsTreeOrganic }
|
||||||
};
|
};
|
||||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(SupportMaterialStyle)
|
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(SupportMaterialStyle)
|
||||||
|
|
||||||
|
@ -4618,6 +4618,17 @@ void PrintConfigDef::init_fff_params()
|
||||||
//Support with too small spacing may touch the object and difficult to remove.
|
//Support with too small spacing may touch the object and difficult to remove.
|
||||||
def->set_default_value(new ConfigOptionFloat(0.35));
|
def->set_default_value(new ConfigOptionFloat(0.35));
|
||||||
|
|
||||||
|
def = this->add("support_object_first_layer_gap", coFloat);
|
||||||
|
def->label = L("Support/object first layer gap");
|
||||||
|
def->category = L("Support");
|
||||||
|
def->tooltip = L("XY separation between an object and its support at the first layer.");
|
||||||
|
def->sidetext = L("mm");
|
||||||
|
def->min = 0;
|
||||||
|
def->max = 10;
|
||||||
|
def->mode = comAdvanced;
|
||||||
|
//Support with too small spacing may touch the object and difficult to remove.
|
||||||
|
def->set_default_value(new ConfigOptionFloat(0.2));
|
||||||
|
|
||||||
def = this->add("support_angle", coFloat);
|
def = this->add("support_angle", coFloat);
|
||||||
def->label = L("Pattern angle");
|
def->label = L("Pattern angle");
|
||||||
def->category = L("Support");
|
def->category = L("Support");
|
||||||
|
@ -5030,16 +5041,6 @@ void PrintConfigDef::init_fff_params()
|
||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionFloat(5.));
|
def->set_default_value(new ConfigOptionFloat(5.));
|
||||||
|
|
||||||
def = this->add("tree_support_branch_diameter_organic", coFloat);
|
|
||||||
def->label = L("Tree support branch diameter");
|
|
||||||
def->category = L("Support");
|
|
||||||
def->tooltip = L("This setting determines the initial diameter of support nodes.");
|
|
||||||
def->sidetext = L("mm");
|
|
||||||
def->min = 1.0;
|
|
||||||
def->max = 10;
|
|
||||||
def->mode = comAdvanced;
|
|
||||||
def->set_default_value(new ConfigOptionFloat(2.));
|
|
||||||
|
|
||||||
def = this->add("tree_support_branch_diameter_angle", coFloat);
|
def = this->add("tree_support_branch_diameter_angle", coFloat);
|
||||||
// TRN PrintSettings: #lmFIXME
|
// TRN PrintSettings: #lmFIXME
|
||||||
def->label = L("Branch Diameter Angle");
|
def->label = L("Branch Diameter Angle");
|
||||||
|
@ -5054,23 +5055,22 @@ void PrintConfigDef::init_fff_params()
|
||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionFloat(5));
|
def->set_default_value(new ConfigOptionFloat(5));
|
||||||
|
|
||||||
def = this->add("tree_support_branch_diameter_double_wall", coFloat);
|
def = this->add("tree_support_branch_diameter_organic", coFloat);
|
||||||
def->label = L("Branch Diameter with double walls");
|
def->label = L("Tree support branch diameter");
|
||||||
def->category = L("Support");
|
def->category = L("Support");
|
||||||
// TRN PrintSettings: "Organic supports" > "Branch Diameter"
|
def->tooltip = L("This setting determines the initial diameter of support nodes.");
|
||||||
def->tooltip = L("Branches with area larger than the area of a circle of this diameter will be printed with double walls for stability. "
|
|
||||||
"Set this value to zero for no double walls.");
|
|
||||||
def->sidetext = L("mm");
|
def->sidetext = L("mm");
|
||||||
def->min = 0;
|
def->min = 1.0;
|
||||||
def->max = 100.f;
|
def->max = 10;
|
||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionFloat(3.));
|
def->set_default_value(new ConfigOptionFloat(2.));
|
||||||
|
|
||||||
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 count of support walls in the range of [0,2]. 0 means auto.");
|
||||||
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(0));
|
||||||
|
|
||||||
|
|
|
@ -132,7 +132,7 @@ enum SupportMaterialPattern {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum SupportMaterialStyle {
|
enum SupportMaterialStyle {
|
||||||
smsDefault, smsGrid, smsSnug, smsTreeSlim, smsTreeStrong, smsTreeHybrid, smsOrganic,
|
smsDefault, smsGrid, smsSnug, smsTreeSlim, smsTreeStrong, smsTreeHybrid, smsTreeOrganic,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum LongRectrationLevel
|
enum LongRectrationLevel
|
||||||
|
@ -840,6 +840,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||||
((ConfigOptionInt, support_threshold_angle))
|
((ConfigOptionInt, support_threshold_angle))
|
||||||
((ConfigOptionFloatOrPercent, support_threshold_overlap))
|
((ConfigOptionFloatOrPercent, support_threshold_overlap))
|
||||||
((ConfigOptionFloat, support_object_xy_distance))
|
((ConfigOptionFloat, support_object_xy_distance))
|
||||||
|
((ConfigOptionFloat, support_object_first_layer_gap))
|
||||||
((ConfigOptionFloat, xy_hole_compensation))
|
((ConfigOptionFloat, xy_hole_compensation))
|
||||||
((ConfigOptionFloat, xy_contour_compensation))
|
((ConfigOptionFloat, xy_contour_compensation))
|
||||||
((ConfigOptionBool, flush_into_objects))
|
((ConfigOptionBool, flush_into_objects))
|
||||||
|
@ -850,9 +851,8 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||||
((ConfigOptionFloat, tree_support_branch_distance))
|
((ConfigOptionFloat, tree_support_branch_distance))
|
||||||
((ConfigOptionFloat, tree_support_tip_diameter))
|
((ConfigOptionFloat, tree_support_tip_diameter))
|
||||||
((ConfigOptionFloat, tree_support_branch_diameter))
|
((ConfigOptionFloat, tree_support_branch_diameter))
|
||||||
((ConfigOptionFloat, tree_support_branch_diameter_angle))
|
|
||||||
((ConfigOptionFloat, tree_support_branch_diameter_double_wall))
|
|
||||||
((ConfigOptionFloat, tree_support_branch_angle))
|
((ConfigOptionFloat, tree_support_branch_angle))
|
||||||
|
((ConfigOptionFloat, tree_support_branch_diameter_angle))
|
||||||
((ConfigOptionFloat, tree_support_angle_slow))
|
((ConfigOptionFloat, tree_support_angle_slow))
|
||||||
((ConfigOptionInt, tree_support_wall_count))
|
((ConfigOptionInt, tree_support_wall_count))
|
||||||
((ConfigOptionBool, tree_support_adaptive_layer_height))
|
((ConfigOptionBool, tree_support_adaptive_layer_height))
|
||||||
|
|
|
@ -633,13 +633,9 @@ void PrintObject::generate_support_material()
|
||||||
if (this->set_started(posSupportMaterial)) {
|
if (this->set_started(posSupportMaterial)) {
|
||||||
this->clear_support_layers();
|
this->clear_support_layers();
|
||||||
|
|
||||||
if ((this->has_support() && m_layers.size() > 1) || (this->has_raft() && ! m_layers.empty())) {
|
if(!has_support() && !m_print->get_no_check_flag()) {
|
||||||
m_print->set_status(50, L("Generating support"));
|
|
||||||
|
|
||||||
this->_generate_support_material();
|
|
||||||
m_print->throw_if_canceled();
|
|
||||||
} else if(!m_print->get_no_check_flag()) {
|
|
||||||
// BBS: pop a warning if objects have significant amount of overhangs but support material is not enabled
|
// BBS: pop a warning if objects have significant amount of overhangs but support material is not enabled
|
||||||
|
// Note: we also need to pop warning if support is disabled and only raft is enabled
|
||||||
m_print->set_status(50, L("Checking support necessity"));
|
m_print->set_status(50, L("Checking support necessity"));
|
||||||
typedef std::chrono::high_resolution_clock clock_;
|
typedef std::chrono::high_resolution_clock clock_;
|
||||||
typedef std::chrono::duration<double, std::ratio<1> > second_;
|
typedef std::chrono::duration<double, std::ratio<1> > second_;
|
||||||
|
@ -669,6 +665,12 @@ void PrintObject::generate_support_material()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((this->has_support() && m_layers.size() > 1) || (this->has_raft() && !m_layers.empty())) {
|
||||||
|
m_print->set_status(50, L("Generating support"));
|
||||||
|
|
||||||
|
this->_generate_support_material();
|
||||||
|
m_print->throw_if_canceled();
|
||||||
|
}
|
||||||
this->set_done(posSupportMaterial);
|
this->set_done(posSupportMaterial);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -731,7 +733,8 @@ void PrintObject::simplify_extrusion_path()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->set_started(posSimplifySupportPath)) {
|
if (this->set_started(posSimplifySupportPath)) {
|
||||||
//BBS: share same progress
|
//BBS: disable circle simplification for support as it causes separation of support walls
|
||||||
|
#if 0
|
||||||
m_print->set_status(75, L("Optimizing toolpath"));
|
m_print->set_status(75, L("Optimizing toolpath"));
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Simplify extrusion path of support in parallel - start";
|
BOOST_LOG_TRIVIAL(debug) << "Simplify extrusion path of support in parallel - start";
|
||||||
tbb::parallel_for(
|
tbb::parallel_for(
|
||||||
|
@ -745,6 +748,7 @@ void PrintObject::simplify_extrusion_path()
|
||||||
);
|
);
|
||||||
m_print->throw_if_canceled();
|
m_print->throw_if_canceled();
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Simplify extrusion path of support in parallel - end";
|
BOOST_LOG_TRIVIAL(debug) << "Simplify extrusion path of support in parallel - end";
|
||||||
|
#endif
|
||||||
this->set_done(posSimplifySupportPath);
|
this->set_done(posSimplifySupportPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -843,14 +847,8 @@ void PrintObject::clear_support_layers()
|
||||||
std::shared_ptr<TreeSupportData> PrintObject::alloc_tree_support_preview_cache()
|
std::shared_ptr<TreeSupportData> PrintObject::alloc_tree_support_preview_cache()
|
||||||
{
|
{
|
||||||
if (!m_tree_support_preview_cache) {
|
if (!m_tree_support_preview_cache) {
|
||||||
const coordf_t layer_height = m_config.layer_height.value;
|
|
||||||
const coordf_t xy_distance = m_config.support_object_xy_distance.value;
|
const coordf_t xy_distance = m_config.support_object_xy_distance.value;
|
||||||
const double angle = m_config.tree_support_branch_angle.value * M_PI / 180.;
|
m_tree_support_preview_cache = std::make_shared<TreeSupportData>(*this, xy_distance, g_config_tree_support_collision_resolution);
|
||||||
const coordf_t max_move_distance
|
|
||||||
= (angle < M_PI / 2) ? (coordf_t)(tan(angle) * layer_height) : std::numeric_limits<coordf_t>::max();
|
|
||||||
const coordf_t radius_sample_resolution = g_config_tree_support_collision_resolution;
|
|
||||||
|
|
||||||
m_tree_support_preview_cache = std::make_shared<TreeSupportData>(*this, xy_distance, max_move_distance, radius_sample_resolution);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_tree_support_preview_cache;
|
return m_tree_support_preview_cache;
|
||||||
|
@ -1015,6 +1013,7 @@ bool PrintObject::invalidate_state_by_config_options(
|
||||||
|| opt_key == "support_base_pattern"
|
|| opt_key == "support_base_pattern"
|
||||||
|| opt_key == "support_style"
|
|| opt_key == "support_style"
|
||||||
|| opt_key == "support_object_xy_distance"
|
|| opt_key == "support_object_xy_distance"
|
||||||
|
|| opt_key == "support_object_first_layer_gap"
|
||||||
|| opt_key == "support_base_pattern_spacing"
|
|| opt_key == "support_base_pattern_spacing"
|
||||||
|| opt_key == "support_expansion"
|
|| opt_key == "support_expansion"
|
||||||
//|| opt_key == "independent_support_layer_height" // BBS
|
//|| opt_key == "independent_support_layer_height" // BBS
|
||||||
|
@ -1036,7 +1035,6 @@ bool PrintObject::invalidate_state_by_config_options(
|
||||||
|| opt_key == "tree_support_branch_diameter"
|
|| opt_key == "tree_support_branch_diameter"
|
||||||
|| opt_key == "tree_support_branch_diameter_organic"
|
|| opt_key == "tree_support_branch_diameter_organic"
|
||||||
|| opt_key == "tree_support_branch_diameter_angle"
|
|| opt_key == "tree_support_branch_diameter_angle"
|
||||||
|| opt_key == "tree_support_branch_diameter_double_wall"
|
|
||||||
|| opt_key == "tree_support_branch_angle"
|
|| opt_key == "tree_support_branch_angle"
|
||||||
|| opt_key == "tree_support_branch_angle_organic"
|
|| opt_key == "tree_support_branch_angle_organic"
|
||||||
|| opt_key == "tree_support_angle_slow"
|
|| opt_key == "tree_support_angle_slow"
|
||||||
|
@ -3935,91 +3933,8 @@ template void PrintObject::remove_bridges_from_contacts<Polygons>(
|
||||||
|
|
||||||
SupportNecessaryType PrintObject::is_support_necessary()
|
SupportNecessaryType PrintObject::is_support_necessary()
|
||||||
{
|
{
|
||||||
static const double super_overhang_area_threshold = SQ(scale_(5.0));
|
|
||||||
const double cantilevel_dist_thresh = scale_(6);
|
const double cantilevel_dist_thresh = scale_(6);
|
||||||
#if 0
|
|
||||||
double threshold_rad = (m_config.support_threshold_angle.value < EPSILON ? 30 : m_config.support_threshold_angle.value + 1) * M_PI / 180.;
|
|
||||||
int enforce_support_layers = m_config.enforce_support_layers;
|
|
||||||
// not fixing in extrusion width % PR b/c never called
|
|
||||||
const coordf_t extrusion_width = m_config.line_width.value;
|
|
||||||
const coordf_t extrusion_width_scaled = scale_(extrusion_width);
|
|
||||||
float max_bridge_length = scale_(m_config.max_bridge_length.value);
|
|
||||||
const bool bridge_no_support = max_bridge_length > 0;// config.bridge_no_support.value;
|
|
||||||
|
|
||||||
for (size_t layer_nr = enforce_support_layers + 1; layer_nr < this->layer_count(); layer_nr++) {
|
|
||||||
Layer* layer = m_layers[layer_nr];
|
|
||||||
Layer* lower_layer = layer->lower_layer;
|
|
||||||
|
|
||||||
coordf_t support_offset_scaled = extrusion_width_scaled * 0.9;
|
|
||||||
ExPolygons lower_layer_offseted = offset_ex(lower_layer->lslices, support_offset_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS);
|
|
||||||
|
|
||||||
// 1. check sharp tail
|
|
||||||
for (const LayerRegion* layerm : layer->regions()) {
|
|
||||||
for (const ExPolygon& expoly : layerm->raw_slices) {
|
|
||||||
// detect sharp tail
|
|
||||||
if (intersection_ex({ expoly }, lower_layer_offseted).empty())
|
|
||||||
return SharpTail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. check overhang area
|
|
||||||
ExPolygons super_overhang_expolys = std::move(diff_ex(layer->lslices, lower_layer_offseted));
|
|
||||||
super_overhang_expolys.erase(std::remove_if(
|
|
||||||
super_overhang_expolys.begin(),
|
|
||||||
super_overhang_expolys.end(),
|
|
||||||
[extrusion_width_scaled](ExPolygon& area) {
|
|
||||||
return offset_ex(area, -0.1 * extrusion_width_scaled).empty();
|
|
||||||
}),
|
|
||||||
super_overhang_expolys.end());
|
|
||||||
|
|
||||||
// remove bridge
|
|
||||||
if (bridge_no_support)
|
|
||||||
remove_bridges_from_contacts(lower_layer, layer, extrusion_width_scaled, &super_overhang_expolys, max_bridge_length);
|
|
||||||
|
|
||||||
Polygons super_overhang_polys = to_polygons(super_overhang_expolys);
|
|
||||||
|
|
||||||
|
|
||||||
super_overhang_polys.erase(std::remove_if(
|
|
||||||
super_overhang_polys.begin(),
|
|
||||||
super_overhang_polys.end(),
|
|
||||||
[extrusion_width_scaled](Polygon& area) {
|
|
||||||
return offset_ex(area, -0.1 * extrusion_width_scaled).empty();
|
|
||||||
}),
|
|
||||||
super_overhang_polys.end());
|
|
||||||
|
|
||||||
double super_overhang_area = 0.0;
|
|
||||||
for (Polygon& poly : super_overhang_polys) {
|
|
||||||
bool is_ccw = poly.is_counter_clockwise();
|
|
||||||
double area_ = poly.area();
|
|
||||||
if (is_ccw) {
|
|
||||||
if (area_ > super_overhang_area_threshold)
|
|
||||||
return LargeOverhang;
|
|
||||||
super_overhang_area += area_;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
super_overhang_area -= area_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//if (super_overhang_area > super_overhang_area_threshold)
|
|
||||||
// return LargeOverhang;
|
|
||||||
|
|
||||||
// 3. check overhang distance
|
|
||||||
const double distance_threshold_scaled = extrusion_width_scaled * 2;
|
|
||||||
ExPolygons lower_layer_offseted_2 = offset_ex(lower_layer->lslices, distance_threshold_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS);
|
|
||||||
ExPolygons exceed_overhang = std::move(diff_ex(super_overhang_polys, lower_layer_offseted_2));
|
|
||||||
exceed_overhang.erase(std::remove_if(
|
|
||||||
exceed_overhang.begin(),
|
|
||||||
exceed_overhang.end(),
|
|
||||||
[extrusion_width_scaled](ExPolygon& area) {
|
|
||||||
// tolerance for 1 extrusion width offset
|
|
||||||
return offset_ex(area, -0.5 * extrusion_width_scaled).empty();
|
|
||||||
}),
|
|
||||||
exceed_overhang.end());
|
|
||||||
if (!exceed_overhang.empty())
|
|
||||||
return LargeOverhang;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
TreeSupport tree_support(*this, m_slicing_params);
|
TreeSupport tree_support(*this, m_slicing_params);
|
||||||
tree_support.support_type = SupportType::stTreeAuto; // need to set support type to fully utilize the power of feature detection
|
tree_support.support_type = SupportType::stTreeAuto; // need to set support type to fully utilize the power of feature detection
|
||||||
tree_support.detect_overhangs(true);
|
tree_support.detect_overhangs(true);
|
||||||
|
@ -4028,7 +3943,7 @@ SupportNecessaryType PrintObject::is_support_necessary()
|
||||||
return SharpTail;
|
return SharpTail;
|
||||||
else if (tree_support.has_cantilever && tree_support.max_cantilever_dist > cantilevel_dist_thresh)
|
else if (tree_support.has_cantilever && tree_support.max_cantilever_dist > cantilevel_dist_thresh)
|
||||||
return Cantilever;
|
return Cantilever;
|
||||||
#endif
|
|
||||||
return NoNeedSupp;
|
return NoNeedSupp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4219,7 +4134,7 @@ static void project_triangles_to_slabs(ConstLayerPtrsAdaptor layers, const index
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintObject::project_and_append_custom_facets(
|
void PrintObject::project_and_append_custom_facets(
|
||||||
bool seam, EnforcerBlockerType type, std::vector<Polygons>& out) const
|
bool seam, EnforcerBlockerType type, std::vector<Polygons>& out, std::vector<std::pair<Vec3f, Vec3f>>* vertical_points) const
|
||||||
{
|
{
|
||||||
for (const ModelVolume* mv : this->model_object()->volumes)
|
for (const ModelVolume* mv : this->model_object()->volumes)
|
||||||
if (mv->is_model_part()) {
|
if (mv->is_model_part()) {
|
||||||
|
@ -4234,7 +4149,7 @@ void PrintObject::project_and_append_custom_facets(
|
||||||
else {
|
else {
|
||||||
std::vector<Polygons> projected;
|
std::vector<Polygons> projected;
|
||||||
// Support blockers or enforcers. Project downward facing painted areas upwards to their respective slicing plane.
|
// Support blockers or enforcers. Project downward facing painted areas upwards to their respective slicing plane.
|
||||||
slice_mesh_slabs(custom_facets, zs_from_layers(this->layers()), this->trafo_centered() * mv->get_matrix(), nullptr, &projected, [](){});
|
slice_mesh_slabs(custom_facets, zs_from_layers(this->layers()), this->trafo_centered() * mv->get_matrix(), nullptr, &projected, vertical_points, [](){});
|
||||||
// Merge these projections with the output, layer by layer.
|
// Merge these projections with the output, layer by layer.
|
||||||
assert(! projected.empty());
|
assert(! projected.empty());
|
||||||
assert(out.empty() || out.size() == projected.size());
|
assert(out.empty() || out.size() == projected.size());
|
||||||
|
|
|
@ -808,10 +808,11 @@ void PrintObject::slice()
|
||||||
std::string warning = fix_slicing_errors(this, m_layers, [this](){ m_print->throw_if_canceled(); }, firstLayerReplacedBy);
|
std::string warning = fix_slicing_errors(this, m_layers, [this](){ m_print->throw_if_canceled(); }, firstLayerReplacedBy);
|
||||||
m_print->throw_if_canceled();
|
m_print->throw_if_canceled();
|
||||||
//BBS: send warning message to slicing callback
|
//BBS: send warning message to slicing callback
|
||||||
if (!warning.empty()) {
|
// This warning is inaccurate, because the empty layers may have been replaced, or the model has supports.
|
||||||
BOOST_LOG_TRIVIAL(info) << warning;
|
//if (!warning.empty()) {
|
||||||
this->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL, warning, PrintStateBase::SlicingReplaceInitEmptyLayers);
|
// BOOST_LOG_TRIVIAL(info) << warning;
|
||||||
}
|
// this->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL, warning, PrintStateBase::SlicingReplaceInitEmptyLayers);
|
||||||
|
//}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Detect and process holes that should be converted to polyholes
|
// Detect and process holes that should be converted to polyholes
|
||||||
|
|
|
@ -1030,6 +1030,9 @@ void reorder_extrusion_entities(std::vector<ExtrusionEntity*> &entities, const s
|
||||||
|
|
||||||
void chain_and_reorder_extrusion_entities(std::vector<ExtrusionEntity*> &entities, const Point *start_near)
|
void chain_and_reorder_extrusion_entities(std::vector<ExtrusionEntity*> &entities, const Point *start_near)
|
||||||
{
|
{
|
||||||
|
// this function crashes if there are empty elements in entities
|
||||||
|
entities.erase(std::remove_if(entities.begin(), entities.end(), [](ExtrusionEntity *entity) { return static_cast<ExtrusionEntityCollection *>(entity)->empty(); }),
|
||||||
|
entities.end());
|
||||||
reorder_extrusion_entities(entities, chain_extrusion_entities(entities, start_near));
|
reorder_extrusion_entities(entities, chain_extrusion_entities(entities, start_near));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ SlicingParameters SlicingParameters::create_from_config(
|
||||||
params.min_layer_height = std::min(params.min_layer_height, params.layer_height);
|
params.min_layer_height = std::min(params.min_layer_height, params.layer_height);
|
||||||
params.max_layer_height = std::max(params.max_layer_height, params.layer_height);
|
params.max_layer_height = std::max(params.max_layer_height, params.layer_height);
|
||||||
|
|
||||||
if (! soluble_interface || is_tree_slim(object_config.support_type.value, object_config.support_style.value)) {
|
if (! soluble_interface) {
|
||||||
params.gap_raft_object = object_config.raft_contact_distance.value;
|
params.gap_raft_object = object_config.raft_contact_distance.value;
|
||||||
//BBS
|
//BBS
|
||||||
params.gap_object_support = object_config.support_bottom_z_distance.value;
|
params.gap_object_support = object_config.support_bottom_z_distance.value;
|
||||||
|
|
|
@ -140,10 +140,11 @@ std::pair<SupportGeneratorLayersPtr, SupportGeneratorLayersPtr> generate_interfa
|
||||||
if (! intermediate_layers.empty() && support_params.has_interfaces()) {
|
if (! intermediate_layers.empty() && support_params.has_interfaces()) {
|
||||||
// For all intermediate layers, collect top contact surfaces, which are not further than support_material_interface_layers.
|
// For all intermediate layers, collect top contact surfaces, which are not further than support_material_interface_layers.
|
||||||
BOOST_LOG_TRIVIAL(debug) << "PrintObjectSupportMaterial::generate_interface_layers() in parallel - start";
|
BOOST_LOG_TRIVIAL(debug) << "PrintObjectSupportMaterial::generate_interface_layers() in parallel - start";
|
||||||
const bool snug_supports = config.support_style.value == smsSnug;
|
const bool snug_supports = support_params.support_style == smsSnug;
|
||||||
const bool smooth_supports = config.support_style.value != 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);
|
||||||
|
@ -329,19 +330,21 @@ SupportGeneratorLayersPtr generate_raft_base(
|
||||||
const BrimType brim_type = object.config().brim_type;
|
const BrimType brim_type = object.config().brim_type;
|
||||||
const bool brim_outer = brim_type == btOuterOnly || brim_type == btOuterAndInner;
|
const bool brim_outer = brim_type == btOuterOnly || brim_type == btOuterAndInner;
|
||||||
const bool brim_inner = brim_type == btInnerOnly || brim_type == btOuterAndInner;
|
const bool brim_inner = brim_type == btInnerOnly || brim_type == btOuterAndInner;
|
||||||
const auto brim_separation = scaled<float>(object.config().brim_object_gap.value + object.config().brim_width.value);
|
// BBS: the pattern of raft and brim are the same, thus the brim can be serpated by support raft.
|
||||||
|
const auto brim_object_gap = scaled<float>(object.config().brim_object_gap.value);
|
||||||
|
//const auto brim_object_gap = scaled<float>(object.config().brim_object_gap.value + object.config().brim_width.value);
|
||||||
for (const ExPolygon &ex : object.layers().front()->lslices) {
|
for (const ExPolygon &ex : object.layers().front()->lslices) {
|
||||||
if (brim_outer && brim_inner)
|
if (brim_outer && brim_inner)
|
||||||
polygons_append(brim, offset(ex, brim_separation));
|
polygons_append(brim, offset(ex, brim_object_gap));
|
||||||
else {
|
else {
|
||||||
if (brim_outer)
|
if (brim_outer)
|
||||||
polygons_append(brim, offset(ex.contour, brim_separation, ClipperLib::jtRound, float(scale_(0.1))));
|
polygons_append(brim, offset(ex.contour, brim_object_gap, ClipperLib::jtRound, float(scale_(0.1))));
|
||||||
else
|
else
|
||||||
brim.emplace_back(ex.contour);
|
brim.emplace_back(ex.contour);
|
||||||
if (brim_inner) {
|
if (brim_inner) {
|
||||||
Polygons holes = ex.holes;
|
Polygons holes = ex.holes;
|
||||||
polygons_reverse(holes);
|
polygons_reverse(holes);
|
||||||
holes = shrink(holes, brim_separation, ClipperLib::jtRound, float(scale_(0.1)));
|
holes = shrink(holes, brim_object_gap, ClipperLib::jtRound, float(scale_(0.1)));
|
||||||
polygons_reverse(holes);
|
polygons_reverse(holes);
|
||||||
polygons_append(brim, std::move(holes));
|
polygons_append(brim, std::move(holes));
|
||||||
} else
|
} else
|
||||||
|
@ -407,7 +410,7 @@ SupportGeneratorLayersPtr generate_raft_base(
|
||||||
// Do not add the raft contact layer, only add the raft layers below the contact layer.
|
// Do not add the raft contact layer, only add the raft layers below the contact layer.
|
||||||
// Insert the 1st layer.
|
// Insert the 1st layer.
|
||||||
{
|
{
|
||||||
SupportGeneratorLayer &new_layer = layer_storage.allocate_unguarded(slicing_params.base_raft_layers > 0 ? SupporLayerType::RaftBase : SupporLayerType::RaftInterface);
|
SupportGeneratorLayer &new_layer = layer_storage.allocate(slicing_params.base_raft_layers > 0 ? SupporLayerType::RaftBase : SupporLayerType::RaftInterface);
|
||||||
raft_layers.push_back(&new_layer);
|
raft_layers.push_back(&new_layer);
|
||||||
new_layer.print_z = slicing_params.first_print_layer_height;
|
new_layer.print_z = slicing_params.first_print_layer_height;
|
||||||
new_layer.height = slicing_params.first_print_layer_height;
|
new_layer.height = slicing_params.first_print_layer_height;
|
||||||
|
@ -441,7 +444,13 @@ SupportGeneratorLayersPtr generate_raft_base(
|
||||||
if (columns_base != nullptr) {
|
if (columns_base != nullptr) {
|
||||||
// Expand the bases of the support columns in the 1st layer.
|
// Expand the bases of the support columns in the 1st layer.
|
||||||
Polygons &raft = columns_base->polygons;
|
Polygons &raft = columns_base->polygons;
|
||||||
Polygons trimming = offset(object.layers().front()->lslices, (float)scale_(support_params.gap_xy), SUPPORT_SURFACES_OFFSET_PARAMETERS);
|
Polygons trimming;
|
||||||
|
// BBS: if first layer of support is intersected with object island, it must have the same function as brim unless in nobrim mode.
|
||||||
|
// brim_object_gap is changed to 0 by default, it's no longer appropriate to use it to determine the gap of first layer support.
|
||||||
|
//if (object.has_brim())
|
||||||
|
// trimming = offset(object.layers().front()->lslices, (float)scale_(object.config().brim_object_gap.value), SUPPORT_SURFACES_OFFSET_PARAMETERS);
|
||||||
|
//else
|
||||||
|
trimming = offset(object.layers().front()->lslices, (float)scale_(support_params.gap_xy_first_layer), SUPPORT_SURFACES_OFFSET_PARAMETERS);
|
||||||
if (inflate_factor_1st_layer > SCALED_EPSILON) {
|
if (inflate_factor_1st_layer > SCALED_EPSILON) {
|
||||||
// Inflate in multiple steps to avoid leaking of the support 1st layer through object walls.
|
// Inflate in multiple steps to avoid leaking of the support 1st layer through object walls.
|
||||||
auto nsteps = std::max(5, int(ceil(inflate_factor_1st_layer / support_params.first_layer_flow.scaled_width())));
|
auto nsteps = std::max(5, int(ceil(inflate_factor_1st_layer / support_params.first_layer_flow.scaled_width())));
|
||||||
|
@ -536,7 +545,7 @@ static Polylines draw_perimeters(const ExPolygon &expoly, double clip_length)
|
||||||
return polylines;
|
return polylines;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tree_supports_generate_paths(
|
void tree_supports_generate_paths(
|
||||||
ExtrusionEntitiesPtr &dst,
|
ExtrusionEntitiesPtr &dst,
|
||||||
const Polygons &polygons,
|
const Polygons &polygons,
|
||||||
const Flow &flow,
|
const Flow &flow,
|
||||||
|
@ -637,22 +646,25 @@ static inline void tree_supports_generate_paths(
|
||||||
ClipperLib_Z::Paths anchor_candidates;
|
ClipperLib_Z::Paths anchor_candidates;
|
||||||
for (ExPolygon& expoly : closing_ex(polygons, float(SCALED_EPSILON), float(SCALED_EPSILON + 0.5 * flow.scaled_width()))) {
|
for (ExPolygon& expoly : closing_ex(polygons, float(SCALED_EPSILON), float(SCALED_EPSILON + 0.5 * flow.scaled_width()))) {
|
||||||
std::unique_ptr<ExtrusionEntityCollection> eec;
|
std::unique_ptr<ExtrusionEntityCollection> eec;
|
||||||
|
ExPolygons regions_to_draw_inner_wall{expoly};
|
||||||
if (support_params.tree_branch_diameter_double_wall_area_scaled > 0)
|
if (support_params.tree_branch_diameter_double_wall_area_scaled > 0)
|
||||||
if (double area = expoly.area(); area > support_params.tree_branch_diameter_double_wall_area_scaled) {
|
if (double area = expoly.area(); area > support_params.tree_branch_diameter_double_wall_area_scaled) {
|
||||||
|
BOOST_LOG_TRIVIAL(debug)<< "TreeSupports: double wall area: " << area<< " > " << support_params.tree_branch_diameter_double_wall_area_scaled;
|
||||||
eec = std::make_unique<ExtrusionEntityCollection>();
|
eec = std::make_unique<ExtrusionEntityCollection>();
|
||||||
// Don't reoder internal / external loops of the same island, always start with the internal loop.
|
// Don't reorder internal / external loops of the same island, always start with the internal loop.
|
||||||
eec->no_sort = true;
|
eec->no_sort = true;
|
||||||
// Make the tree branch stable by adding another perimeter.
|
// Make the tree branch stable by adding another perimeter.
|
||||||
ExPolygons level2 = offset2_ex({ expoly }, -1.5 * flow.scaled_width(), 0.5 * flow.scaled_width());
|
ExPolygons level2 = offset2_ex({expoly}, -1.5 * flow.scaled_width(), 0.5 * flow.scaled_width());
|
||||||
if (level2.size() == 1) {
|
if (level2.size() > 0) {
|
||||||
Polylines polylines;
|
regions_to_draw_inner_wall = level2;
|
||||||
extrusion_entities_append_paths(eec->entities, draw_perimeters(expoly, clip_length), ExtrusionRole::erSupportMaterial, flow.mm3_per_mm(), flow.width(), flow.height(),
|
extrusion_entities_append_paths(eec->entities, draw_perimeters(expoly, clip_length), ExtrusionRole::erSupportMaterial, flow.mm3_per_mm(), flow.width(), flow.height(),
|
||||||
// Disable reversal of the path, always start with the anchor, always print CCW.
|
// Disable reversal of the path, always start with the anchor, always print CCW.
|
||||||
false);
|
false);
|
||||||
expoly = level2.front();
|
expoly = level2.front();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (ExPolygon &expoly : regions_to_draw_inner_wall)
|
||||||
|
{
|
||||||
// Try to produce one more perimeter to place the seam anchor.
|
// Try to produce one more perimeter to place the seam anchor.
|
||||||
// First genrate a 2nd perimeter loop as a source for anchor candidates.
|
// First genrate a 2nd perimeter loop as a source for anchor candidates.
|
||||||
// The anchor candidate points are annotated with an index of the source contour or with -1 if on intersection.
|
// The anchor candidate points are annotated with an index of the source contour or with -1 if on intersection.
|
||||||
|
@ -660,13 +672,12 @@ static inline void tree_supports_generate_paths(
|
||||||
shrink_expolygon_with_contour_idx(expoly, flow.scaled_width(), DefaultJoinType, 1.2, anchor_candidates);
|
shrink_expolygon_with_contour_idx(expoly, flow.scaled_width(), DefaultJoinType, 1.2, anchor_candidates);
|
||||||
// Orient all contours CW.
|
// Orient all contours CW.
|
||||||
for (auto &path : anchor_candidates)
|
for (auto &path : anchor_candidates)
|
||||||
if (ClipperLib_Z::Area(path) > 0)
|
if (ClipperLib_Z::Area(path) > 0) std::reverse(path.begin(), path.end());
|
||||||
std::reverse(path.begin(), path.end());
|
|
||||||
|
|
||||||
// Draw the perimeters.
|
// Draw the perimeters.
|
||||||
Polylines polylines;
|
Polylines polylines;
|
||||||
polylines.reserve(expoly.holes.size() + 1);
|
polylines.reserve(expoly.holes.size() + 1);
|
||||||
for (int idx_loop = 0; idx_loop < int(expoly.num_contours()); ++ idx_loop) {
|
for (int idx_loop = 0; idx_loop < int(expoly.num_contours()); ++idx_loop) {
|
||||||
// Open the loop with a seam.
|
// Open the loop with a seam.
|
||||||
const Polygon &loop = expoly.contour_or_hole(idx_loop);
|
const Polygon &loop = expoly.contour_or_hole(idx_loop);
|
||||||
Polyline pl(loop.points);
|
Polyline pl(loop.points);
|
||||||
|
@ -676,8 +687,7 @@ static inline void tree_supports_generate_paths(
|
||||||
pl.reverse();
|
pl.reverse();
|
||||||
pl.points.emplace_back(pl.points.front());
|
pl.points.emplace_back(pl.points.front());
|
||||||
pl.clip_end(clip_length);
|
pl.clip_end(clip_length);
|
||||||
if (pl.size() < 2)
|
if (pl.size() < 2) continue;
|
||||||
continue;
|
|
||||||
// Find the foot of the seam point on anchor_candidates. Only pick an anchor point that was created by offsetting the source contour.
|
// Find the foot of the seam point on anchor_candidates. Only pick an anchor point that was created by offsetting the source contour.
|
||||||
ClipperLib_Z::Path *closest_contour = nullptr;
|
ClipperLib_Z::Path *closest_contour = nullptr;
|
||||||
Vec2d closest_point;
|
Vec2d closest_point;
|
||||||
|
@ -686,7 +696,7 @@ static inline void tree_supports_generate_paths(
|
||||||
double d2min = std::numeric_limits<double>::max();
|
double d2min = std::numeric_limits<double>::max();
|
||||||
Vec2d seam_pt = pl.back().cast<double>();
|
Vec2d seam_pt = pl.back().cast<double>();
|
||||||
for (ClipperLib_Z::Path &path : anchor_candidates)
|
for (ClipperLib_Z::Path &path : anchor_candidates)
|
||||||
for (int i = 0; i < int(path.size()); ++ i) {
|
for (int i = 0; i < int(path.size()); ++i) {
|
||||||
int j = next_idx_modulo(i, path);
|
int j = next_idx_modulo(i, path);
|
||||||
if (path[i].z() == idx_loop || path[j].z() == idx_loop) {
|
if (path[i].z() == idx_loop || path[j].z() == idx_loop) {
|
||||||
Vec2d pi(path[i].x(), path[i].y());
|
Vec2d pi(path[i].x(), path[i].y());
|
||||||
|
@ -755,6 +765,7 @@ static inline void tree_supports_generate_paths(
|
||||||
extrusion_entities_append_paths(out, std::move(polylines), ExtrusionRole::erSupportMaterial, flow.mm3_per_mm(), flow.width(), flow.height(),
|
extrusion_entities_append_paths(out, std::move(polylines), ExtrusionRole::erSupportMaterial, flow.mm3_per_mm(), flow.width(), flow.height(),
|
||||||
// Disable reversal of the path, always start with the anchor, always print CCW.
|
// Disable reversal of the path, always start with the anchor, always print CCW.
|
||||||
false);
|
false);
|
||||||
|
}
|
||||||
if (eec) {
|
if (eec) {
|
||||||
std::reverse(eec->entities.begin(), eec->entities.end());
|
std::reverse(eec->entities.begin(), eec->entities.end());
|
||||||
dst.emplace_back(eec.release());
|
dst.emplace_back(eec.release());
|
||||||
|
@ -762,20 +773,27 @@ static inline void tree_supports_generate_paths(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void fill_expolygons_with_sheath_generate_paths(
|
void fill_expolygons_with_sheath_generate_paths(
|
||||||
ExtrusionEntitiesPtr &dst,
|
ExtrusionEntitiesPtr &dst,
|
||||||
const Polygons &polygons,
|
const Polygons &polygons,
|
||||||
Fill *filler,
|
Fill *filler,
|
||||||
float density,
|
float density,
|
||||||
ExtrusionRole role,
|
ExtrusionRole role,
|
||||||
const Flow &flow,
|
const Flow &flow,
|
||||||
|
const SupportParameters& support_params,
|
||||||
bool with_sheath,
|
bool with_sheath,
|
||||||
bool no_sort)
|
bool no_sort)
|
||||||
{
|
{
|
||||||
if (polygons.empty())
|
if (polygons.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (! with_sheath) {
|
if (with_sheath) {
|
||||||
|
if (density == 0) {
|
||||||
|
tree_supports_generate_paths(dst, polygons, flow, support_params);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
fill_expolygons_generate_paths(dst, closing_ex(polygons, float(SCALED_EPSILON)), filler, density, role, flow);
|
fill_expolygons_generate_paths(dst, closing_ex(polygons, float(SCALED_EPSILON)), filler, density, role, flow);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1399,6 +1417,10 @@ SupportGeneratorLayersPtr generate_support_layers(
|
||||||
append(layers_sorted, intermediate_layers);
|
append(layers_sorted, intermediate_layers);
|
||||||
append(layers_sorted, interface_layers);
|
append(layers_sorted, interface_layers);
|
||||||
append(layers_sorted, base_interface_layers);
|
append(layers_sorted, base_interface_layers);
|
||||||
|
// remove dupliated layers
|
||||||
|
std::sort(layers_sorted.begin(), layers_sorted.end());
|
||||||
|
layers_sorted.erase(std::unique(layers_sorted.begin(), layers_sorted.end()), layers_sorted.end());
|
||||||
|
|
||||||
// Sort the layers lexicographically by a raising print_z and a decreasing height.
|
// Sort the layers lexicographically by a raising print_z and a decreasing height.
|
||||||
std::sort(layers_sorted.begin(), layers_sorted.end(), [](auto *l1, auto *l2) { return *l1 < *l2; });
|
std::sort(layers_sorted.begin(), layers_sorted.end(), [](auto *l1, auto *l2) { return *l1 < *l2; });
|
||||||
int layer_id = 0;
|
int layer_id = 0;
|
||||||
|
@ -1531,7 +1553,7 @@ void generate_support_toolpaths(
|
||||||
filler, float(support_params.support_density),
|
filler, float(support_params.support_density),
|
||||||
// Extrusion parameters
|
// Extrusion parameters
|
||||||
ExtrusionRole::erSupportMaterial, flow,
|
ExtrusionRole::erSupportMaterial, flow,
|
||||||
support_params.with_sheath, false);
|
support_params, support_params.with_sheath, false);
|
||||||
}
|
}
|
||||||
if (! tree_polygons.empty())
|
if (! tree_polygons.empty())
|
||||||
tree_supports_generate_paths(support_layer.support_fills.entities, tree_polygons, flow, support_params);
|
tree_supports_generate_paths(support_layer.support_fills.entities, tree_polygons, flow, support_params);
|
||||||
|
@ -1566,7 +1588,7 @@ void generate_support_toolpaths(
|
||||||
// Extrusion parameters
|
// Extrusion parameters
|
||||||
(support_layer_id < slicing_params.base_raft_layers) ? ExtrusionRole::erSupportMaterial : ExtrusionRole::erSupportMaterialInterface, flow,
|
(support_layer_id < slicing_params.base_raft_layers) ? ExtrusionRole::erSupportMaterial : ExtrusionRole::erSupportMaterialInterface, flow,
|
||||||
// sheath at first layer
|
// sheath at first layer
|
||||||
support_layer_id == 0, support_layer_id == 0);
|
support_params, support_layer_id == 0, support_layer_id == 0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1630,7 +1652,7 @@ void generate_support_toolpaths(
|
||||||
{
|
{
|
||||||
SupportLayer &support_layer = *support_layers[support_layer_id];
|
SupportLayer &support_layer = *support_layers[support_layer_id];
|
||||||
LayerCache &layer_cache = layer_caches[support_layer_id];
|
LayerCache &layer_cache = layer_caches[support_layer_id];
|
||||||
const float support_interface_angle = config.support_style.value == smsGrid ?
|
const float support_interface_angle = (support_params.support_style == smsGrid || config.support_interface_pattern == smipRectilinear) ?
|
||||||
support_params.interface_angle : support_params.raft_interface_angle(support_layer.interface_id());
|
support_params.interface_angle : support_params.raft_interface_angle(support_layer.interface_id());
|
||||||
|
|
||||||
// Find polygons with the same print_z.
|
// Find polygons with the same print_z.
|
||||||
|
@ -1734,7 +1756,7 @@ void generate_support_toolpaths(
|
||||||
// Filler and its parameters
|
// Filler and its parameters
|
||||||
filler, float(density),
|
filler, float(density),
|
||||||
// Extrusion parameters
|
// Extrusion parameters
|
||||||
ExtrusionRole::erSupportMaterialInterface, interface_flow);
|
interface_as_base ? ExtrusionRole::erSupportMaterial : ExtrusionRole::erSupportMaterialInterface, interface_flow);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const bool top_interfaces = config.support_interface_top_layers.value != 0;
|
const bool top_interfaces = config.support_interface_top_layers.value != 0;
|
||||||
|
@ -1792,10 +1814,12 @@ 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));
|
||||||
sheath = true;
|
sheath = true;
|
||||||
no_sort = true;
|
no_sort = true;
|
||||||
} else if (config.support_style == SupportMaterialStyle::smsOrganic ||
|
} else if (support_params.support_style == SupportMaterialStyle::smsTreeOrganic) {
|
||||||
// Orca: use organic as default
|
// if the tree supports are too tall, use double wall to make it stronger
|
||||||
config.support_style == smsDefault) {
|
SupportParameters support_params2 = support_params;
|
||||||
tree_supports_generate_paths(base_layer.extrusions, base_layer.polygons_to_extrude(), flow, support_params);
|
if (support_layer.print_z > 100.0)
|
||||||
|
support_params2.tree_branch_diameter_double_wall_area_scaled = 0.1;
|
||||||
|
tree_supports_generate_paths(base_layer.extrusions, base_layer.polygons_to_extrude(), flow, support_params2);
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
if (! done)
|
if (! done)
|
||||||
|
@ -1808,7 +1832,7 @@ void generate_support_toolpaths(
|
||||||
filler, density,
|
filler, density,
|
||||||
// Extrusion parameters
|
// Extrusion parameters
|
||||||
ExtrusionRole::erSupportMaterial, flow,
|
ExtrusionRole::erSupportMaterial, flow,
|
||||||
sheath, no_sort);
|
support_params, sheath, no_sort);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge base_interface_layers to base_layers to avoid unneccessary retractions
|
// Merge base_interface_layers to base_layers to avoid unneccessary retractions
|
||||||
|
|
|
@ -50,6 +50,11 @@ 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(
|
||||||
|
ExtrusionEntitiesPtr &dst, const Polygons &polygons, Fill *filler, float density, ExtrusionRole role, const Flow &flow, const SupportParameters& support_params, bool with_sheath, bool no_sort);
|
||||||
|
|
||||||
// returns sorted layers
|
// returns sorted layers
|
||||||
SupportGeneratorLayersPtr generate_support_layers(
|
SupportGeneratorLayersPtr generate_support_layers(
|
||||||
PrintObject &object,
|
PrintObject &object,
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -6,6 +6,7 @@
|
||||||
#include "Slicing.hpp"
|
#include "Slicing.hpp"
|
||||||
#include "Fill/FillBase.hpp"
|
#include "Fill/FillBase.hpp"
|
||||||
#include "SupportLayer.hpp"
|
#include "SupportLayer.hpp"
|
||||||
|
#include "SupportParameters.hpp"
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
class PrintObject;
|
class PrintObject;
|
||||||
|
@ -18,35 +19,6 @@ class PrintObjectConfig;
|
||||||
// the parameters of the raft to determine the 1st layer height and thickness.
|
// the parameters of the raft to determine the 1st layer height and thickness.
|
||||||
class PrintObjectSupportMaterial
|
class PrintObjectSupportMaterial
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
|
|
||||||
struct SupportParams {
|
|
||||||
Flow first_layer_flow;
|
|
||||||
Flow support_material_flow;
|
|
||||||
Flow support_material_interface_flow;
|
|
||||||
Flow support_material_bottom_interface_flow;
|
|
||||||
// Is merging of regions allowed? Could the interface & base support regions be printed with the same extruder?
|
|
||||||
bool can_merge_support_regions;
|
|
||||||
|
|
||||||
coordf_t support_layer_height_min;
|
|
||||||
// coordf_t support_layer_height_max;
|
|
||||||
|
|
||||||
coordf_t gap_xy;
|
|
||||||
|
|
||||||
float base_angle;
|
|
||||||
float interface_angle;
|
|
||||||
coordf_t interface_spacing;
|
|
||||||
coordf_t support_expansion;
|
|
||||||
coordf_t interface_density;
|
|
||||||
coordf_t support_spacing;
|
|
||||||
coordf_t support_density;
|
|
||||||
|
|
||||||
InfillPattern base_fill_pattern;
|
|
||||||
InfillPattern interface_fill_pattern;
|
|
||||||
InfillPattern contact_fill_pattern;
|
|
||||||
bool with_sheath;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PrintObjectSupportMaterial(const PrintObject *object, const SlicingParameters &slicing_params);
|
PrintObjectSupportMaterial(const PrintObject *object, const SlicingParameters &slicing_params);
|
||||||
|
|
||||||
|
@ -97,24 +69,6 @@ private:
|
||||||
SupportGeneratorLayersPtr &intermediate_layers,
|
SupportGeneratorLayersPtr &intermediate_layers,
|
||||||
const std::vector<Polygons> &layer_support_areas) const;
|
const std::vector<Polygons> &layer_support_areas) const;
|
||||||
|
|
||||||
// Generate raft layers, also expand the 1st support layer
|
|
||||||
// in case there is no raft layer to improve support adhesion.
|
|
||||||
SupportGeneratorLayersPtr generate_raft_base(
|
|
||||||
const PrintObject &object,
|
|
||||||
const SupportGeneratorLayersPtr &top_contacts,
|
|
||||||
const SupportGeneratorLayersPtr &interface_layers,
|
|
||||||
const SupportGeneratorLayersPtr &base_interface_layers,
|
|
||||||
const SupportGeneratorLayersPtr &base_layers,
|
|
||||||
SupportGeneratorLayerStorage &layer_storage) const;
|
|
||||||
|
|
||||||
// Turn some of the base layers into base interface layers.
|
|
||||||
// For soluble interfaces with non-soluble bases, print maximum two first interface layers with the base
|
|
||||||
// extruder to improve adhesion of the soluble filament to the base.
|
|
||||||
std::pair<SupportGeneratorLayersPtr, SupportGeneratorLayersPtr> generate_interface_layers(
|
|
||||||
const SupportGeneratorLayersPtr &bottom_contacts,
|
|
||||||
const SupportGeneratorLayersPtr &top_contacts,
|
|
||||||
SupportGeneratorLayersPtr &intermediate_layers,
|
|
||||||
SupportGeneratorLayerStorage &layer_storage) const;
|
|
||||||
|
|
||||||
|
|
||||||
// Trim support layers by an object to leave a defined gap between
|
// Trim support layers by an object to leave a defined gap between
|
||||||
|
@ -131,16 +85,6 @@ private:
|
||||||
void clip_with_shape();
|
void clip_with_shape();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Produce the actual G-code.
|
|
||||||
void generate_toolpaths(
|
|
||||||
SupportLayerPtrs &support_layers,
|
|
||||||
const SupportGeneratorLayersPtr &raft_layers,
|
|
||||||
const SupportGeneratorLayersPtr &bottom_contacts,
|
|
||||||
const SupportGeneratorLayersPtr &top_contacts,
|
|
||||||
const SupportGeneratorLayersPtr &intermediate_layers,
|
|
||||||
const SupportGeneratorLayersPtr &interface_layers,
|
|
||||||
const SupportGeneratorLayersPtr &base_interface_layers) const;
|
|
||||||
|
|
||||||
// Following objects are not owned by SupportMaterial class.
|
// Following objects are not owned by SupportMaterial class.
|
||||||
const PrintObject *m_object;
|
const PrintObject *m_object;
|
||||||
const PrintConfig *m_print_config;
|
const PrintConfig *m_print_config;
|
||||||
|
@ -149,7 +93,7 @@ private:
|
||||||
// carrying information on a raft, 1st layer height, 1st object layer height, gap between the raft and object etc.
|
// carrying information on a raft, 1st layer height, 1st object layer height, gap between the raft and object etc.
|
||||||
SlicingParameters m_slicing_params;
|
SlicingParameters m_slicing_params;
|
||||||
// Various precomputed support parameters to be shared with external functions.
|
// Various precomputed support parameters to be shared with external functions.
|
||||||
SupportParams m_support_params;
|
SupportParameters m_support_params;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
|
@ -1,20 +1,18 @@
|
||||||
#ifndef slic3r_SupportParameters_hpp_
|
#ifndef slic3r_SupportParameters_hpp_
|
||||||
#define slic3r_SupportParameters_hpp_
|
#define slic3r_SupportParameters_hpp_
|
||||||
|
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
#include "../libslic3r.h"
|
#include "../libslic3r.h"
|
||||||
#include "../Flow.hpp"
|
#include "../Flow.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
class PrintObject;
|
|
||||||
enum InfillPattern : int;
|
|
||||||
|
|
||||||
struct SupportParameters {
|
struct SupportParameters {
|
||||||
SupportParameters(const PrintObject &object)
|
SupportParameters() = delete;
|
||||||
|
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 =
|
||||||
|
@ -26,23 +24,25 @@ struct SupportParameters {
|
||||||
(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;
|
|
||||||
this->num_bottom_interface_layers = this->has_bottom_contacts ? size_t(num_bottom_interface_layers - 1) : 0;
|
|
||||||
if (this->soluble_interface_non_soluble_base) {
|
if (this->soluble_interface_non_soluble_base) {
|
||||||
// Try to support soluble dense interfaces with non-soluble dense interfaces.
|
// Try to support soluble dense interfaces with non-soluble dense interfaces.
|
||||||
this->num_top_base_interface_layers = size_t(std::min(num_top_interface_layers / 2, 2));
|
this->num_top_base_interface_layers = size_t(std::min(int(num_top_interface_layers) / 2, 2));
|
||||||
this->num_bottom_base_interface_layers = size_t(std::min(num_bottom_interface_layers / 2, 2));
|
this->num_bottom_base_interface_layers = size_t(std::min(int(num_bottom_interface_layers) / 2, 2));
|
||||||
} else {
|
} else {
|
||||||
this->num_top_base_interface_layers = 0;
|
// BBS: if support interface and support base do not use the same filament, add a base layer to improve their adhesion
|
||||||
this->num_bottom_base_interface_layers = 0;
|
// Note: support materials (such as Supp.W) can't be used as support base now, so support interface and base are still using different filaments even if
|
||||||
|
// support_filament==0
|
||||||
|
bool differnt_support_interface_filament = object_config.support_interface_filament != 0 &&
|
||||||
|
object_config.support_interface_filament != object_config.support_filament;
|
||||||
|
this->num_top_base_interface_layers = differnt_support_interface_filament ? 1 : 0;
|
||||||
|
this->num_bottom_base_interface_layers = differnt_support_interface_filament ? 1 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->first_layer_flow = Slic3r::support_material_1st_layer_flow(&object, float(slicing_params.first_print_layer_height));
|
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_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->support_material_interface_flow = Slic3r::support_material_interface_flow(&object, float(slicing_params.layer_height));
|
||||||
|
@ -69,10 +69,11 @@ struct SupportParameters {
|
||||||
external_perimeter_width = std::max(external_perimeter_width, coordf_t(region.flow(object, frExternalPerimeter, slicing_params.layer_height).width()));
|
external_perimeter_width = std::max(external_perimeter_width, coordf_t(region.flow(object, frExternalPerimeter, slicing_params.layer_height).width()));
|
||||||
bridge_flow_ratio += region.config().bridge_flow;
|
bridge_flow_ratio += region.config().bridge_flow;
|
||||||
}
|
}
|
||||||
this->gap_xy = object_config.support_object_xy_distance;//.get_abs_value(external_perimeter_width);
|
this->gap_xy = object_config.support_object_xy_distance.value;
|
||||||
|
this->gap_xy_first_layer = object_config.support_object_first_layer_gap.value;
|
||||||
bridge_flow_ratio /= object.num_printing_regions();
|
bridge_flow_ratio /= object.num_printing_regions();
|
||||||
|
|
||||||
this->support_material_bottom_interface_flow = slicing_params.soluble_interface || ! object_config.thick_bridges ?
|
this->support_material_bottom_interface_flow = slicing_params.soluble_interface || !object_config.thick_bridges ?
|
||||||
this->support_material_interface_flow.with_flow_ratio(bridge_flow_ratio) :
|
this->support_material_interface_flow.with_flow_ratio(bridge_flow_ratio) :
|
||||||
Flow::bridging_flow(bridge_flow_ratio * this->support_material_interface_flow.nozzle_diameter(), this->support_material_interface_flow.nozzle_diameter());
|
Flow::bridging_flow(bridge_flow_ratio * this->support_material_interface_flow.nozzle_diameter(), this->support_material_interface_flow.nozzle_diameter());
|
||||||
|
|
||||||
|
@ -86,32 +87,39 @@ struct SupportParameters {
|
||||||
this->can_merge_support_regions = true;
|
this->can_merge_support_regions = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
double interface_spacing = object_config.support_interface_spacing.value + this->support_material_interface_flow.spacing();
|
|
||||||
this->interface_density = std::min(1., this->support_material_interface_flow.spacing() / interface_spacing);
|
this->base_angle = Geometry::deg2rad(float(object_config.support_angle.value));
|
||||||
|
this->interface_angle = Geometry::deg2rad(float(object_config.support_angle.value + 90.));
|
||||||
|
this->interface_spacing = object_config.support_interface_spacing.value + this->support_material_interface_flow.spacing();
|
||||||
|
this->interface_density = std::min(1., this->support_material_interface_flow.spacing() / this->interface_spacing);
|
||||||
double raft_interface_spacing = object_config.support_interface_spacing.value + this->raft_interface_flow.spacing();
|
double raft_interface_spacing = object_config.support_interface_spacing.value + this->raft_interface_flow.spacing();
|
||||||
this->raft_interface_density = std::min(1., this->raft_interface_flow.spacing() / raft_interface_spacing);
|
this->raft_interface_density = std::min(1., this->raft_interface_flow.spacing() / raft_interface_spacing);
|
||||||
double support_spacing = object_config.support_base_pattern_spacing.value + this->support_material_flow.spacing();
|
this->support_spacing = object_config.support_base_pattern_spacing.value + this->support_material_flow.spacing();
|
||||||
this->support_density = std::min(1., this->support_material_flow.spacing() / support_spacing);
|
this->support_density = std::min(1., this->support_material_flow.spacing() / this->support_spacing);
|
||||||
if (object_config.support_interface_top_layers.value == 0) {
|
if (object_config.support_interface_top_layers.value == 0) {
|
||||||
// No interface layers allowed, print everything with the base support pattern.
|
// No interface layers allowed, print everything with the base support pattern.
|
||||||
|
this->interface_spacing = this->support_spacing;
|
||||||
this->interface_density = this->support_density;
|
this->interface_density = this->support_density;
|
||||||
}
|
}
|
||||||
|
|
||||||
SupportMaterialPattern support_pattern = object_config.support_base_pattern;
|
SupportMaterialPattern support_pattern = object_config.support_base_pattern;
|
||||||
this->with_sheath = false;//object_config.support_material_with_sheath;
|
this->with_sheath = 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;
|
||||||
this->interface_fill_pattern = (this->interface_density > 0.95 ? ipRectilinear : ipSupportBase);
|
this->interface_fill_pattern = (this->interface_density > 0.95 ? ipRectilinear : ipSupportBase);
|
||||||
this->raft_interface_fill_pattern = this->raft_interface_density > 0.95 ? ipRectilinear : ipSupportBase;
|
this->raft_interface_fill_pattern = this->raft_interface_density > 0.95 ? ipRectilinear : ipSupportBase;
|
||||||
|
if (object_config.support_interface_pattern == smipGrid)
|
||||||
|
this->contact_fill_pattern = ipGrid;
|
||||||
|
else if (object_config.support_interface_pattern == smipRectilinearInterlaced)
|
||||||
|
this->contact_fill_pattern = ipRectilinear;
|
||||||
|
else
|
||||||
this->contact_fill_pattern =
|
this->contact_fill_pattern =
|
||||||
(object_config.support_interface_pattern == smipAuto && slicing_params.soluble_interface) ||
|
(object_config.support_interface_pattern == smipAuto && slicing_params.soluble_interface) ||
|
||||||
object_config.support_interface_pattern == smipConcentric ?
|
object_config.support_interface_pattern == smipConcentric ?
|
||||||
ipConcentric :
|
ipConcentric :
|
||||||
(this->interface_density > 0.95 ? ipRectilinear : ipSupportBase);
|
(this->interface_density > 0.95 ? ipRectilinear : ipSupportBase);
|
||||||
|
|
||||||
this->base_angle = Geometry::deg2rad(float(object_config.support_angle.value));
|
|
||||||
this->interface_angle = Geometry::deg2rad(float(object_config.support_angle.value + 90.));
|
|
||||||
this->raft_angle_1st_layer = 0.f;
|
this->raft_angle_1st_layer = 0.f;
|
||||||
this->raft_angle_base = 0.f;
|
this->raft_angle_base = 0.f;
|
||||||
this->raft_angle_interface = 0.f;
|
this->raft_angle_interface = 0.f;
|
||||||
|
@ -143,9 +151,34 @@ struct SupportParameters {
|
||||||
assert(slicing_params.raft_layers() == 0);
|
assert(slicing_params.raft_layers() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->tree_branch_diameter_double_wall_area_scaled = 0.25 * sqr(scaled<double>(object_config.tree_support_branch_diameter_double_wall.value)) * M_PI;
|
const auto nozzle_diameter = print_config.nozzle_diameter.get_at(object_config.support_interface_filament - 1);
|
||||||
}
|
const coordf_t extrusion_width = object_config.line_width.get_abs_value(nozzle_diameter);
|
||||||
|
support_extrusion_width = object_config.support_line_width.get_abs_value(nozzle_diameter);
|
||||||
|
support_extrusion_width = support_extrusion_width > 0 ? support_extrusion_width : extrusion_width;
|
||||||
|
|
||||||
|
independent_layer_height = print_config.independent_support_layer_height;
|
||||||
|
|
||||||
|
// 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 :
|
||||||
|
object_config.tree_support_wall_count.value == 0 ? 0.25 * sqr(scaled<double>(5.0)) * M_PI :
|
||||||
|
std::numeric_limits<double>::max();
|
||||||
|
|
||||||
|
support_style = object_config.support_style;
|
||||||
|
if (support_style != smsDefault) {
|
||||||
|
if ((support_style == smsSnug || support_style == smsGrid) && is_tree(object_config.support_type)) support_style = smsDefault;
|
||||||
|
if ((support_style == smsTreeSlim || support_style == smsTreeStrong || support_style == smsTreeHybrid || support_style == smsTreeOrganic) &&
|
||||||
|
!is_tree(object_config.support_type))
|
||||||
|
support_style = smsDefault;
|
||||||
|
}
|
||||||
|
if (support_style == smsDefault) {
|
||||||
|
if (is_tree(object_config.support_type)) {
|
||||||
|
// Orca: use organic as default
|
||||||
|
support_style = smsTreeOrganic;
|
||||||
|
} else {
|
||||||
|
support_style = smsGrid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// Both top / bottom contacts and interfaces are soluble.
|
// Both top / bottom contacts and interfaces are soluble.
|
||||||
bool soluble_interface;
|
bool soluble_interface;
|
||||||
// Support contact & interface are soluble, but support base is non-soluble.
|
// Support contact & interface are soluble, but support base is non-soluble.
|
||||||
|
@ -181,6 +214,7 @@ struct SupportParameters {
|
||||||
Flow support_material_bottom_interface_flow;
|
Flow support_material_bottom_interface_flow;
|
||||||
// Flow at raft inteface & contact layers.
|
// Flow at raft inteface & contact layers.
|
||||||
Flow raft_interface_flow;
|
Flow raft_interface_flow;
|
||||||
|
coordf_t support_extrusion_width;
|
||||||
// Is merging of regions allowed? Could the interface & base support regions be printed with the same extruder?
|
// Is merging of regions allowed? Could the interface & base support regions be printed with the same extruder?
|
||||||
bool can_merge_support_regions;
|
bool can_merge_support_regions;
|
||||||
|
|
||||||
|
@ -188,16 +222,20 @@ struct SupportParameters {
|
||||||
// coordf_t support_layer_height_max;
|
// coordf_t support_layer_height_max;
|
||||||
|
|
||||||
coordf_t gap_xy;
|
coordf_t gap_xy;
|
||||||
|
coordf_t gap_xy_first_layer;
|
||||||
|
|
||||||
float base_angle;
|
float base_angle;
|
||||||
float interface_angle;
|
float interface_angle;
|
||||||
|
coordf_t interface_spacing;
|
||||||
|
coordf_t support_expansion=0;
|
||||||
// Density of the top / bottom interface and contact layers.
|
// Density of the top / bottom interface and contact layers.
|
||||||
coordf_t interface_density;
|
coordf_t interface_density;
|
||||||
// Density of the raft interface and contact layers.
|
// Density of the raft interface and contact layers.
|
||||||
coordf_t raft_interface_density;
|
coordf_t raft_interface_density;
|
||||||
|
coordf_t support_spacing;
|
||||||
// Density of the base support layers.
|
// Density of the base support layers.
|
||||||
coordf_t support_density;
|
coordf_t support_density;
|
||||||
|
SupportMaterialStyle support_style = smsDefault;
|
||||||
|
|
||||||
// Pattern of the sparse infill including sparse raft layers.
|
// Pattern of the sparse infill including sparse raft layers.
|
||||||
InfillPattern base_fill_pattern;
|
InfillPattern base_fill_pattern;
|
||||||
|
@ -210,7 +248,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;
|
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;
|
||||||
|
@ -219,6 +257,9 @@ struct SupportParameters {
|
||||||
// Produce a raft interface angle for a given SupportLayer::interface_id()
|
// Produce a raft interface angle for a given SupportLayer::interface_id()
|
||||||
float raft_interface_angle(size_t interface_id) const
|
float raft_interface_angle(size_t interface_id) const
|
||||||
{ return this->raft_angle_interface + ((interface_id & 1) ? float(- M_PI / 4.) : float(+ M_PI / 4.)); }
|
{ return this->raft_angle_interface + ((interface_id & 1) ? float(- M_PI / 4.) : float(+ M_PI / 4.)); }
|
||||||
|
|
||||||
|
bool independent_layer_height = false;
|
||||||
|
const double thresh_big_overhang = Slic3r::sqr(scale_(10));
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
|
@ -33,7 +33,7 @@ using namespace std::literals;
|
||||||
|
|
||||||
// or warning
|
// or warning
|
||||||
// had to use a define beacuse the macro processing inside macro BOOST_LOG_TRIVIAL()
|
// had to use a define beacuse the macro processing inside macro BOOST_LOG_TRIVIAL()
|
||||||
#define error_level_not_in_cache error
|
#define error_level_not_in_cache debug
|
||||||
|
|
||||||
//FIXME Machine border is currently ignored.
|
//FIXME Machine border is currently ignored.
|
||||||
static Polygons calculateMachineBorderCollision(Polygon machine_border)
|
static Polygons calculateMachineBorderCollision(Polygon machine_border)
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -11,6 +11,8 @@
|
||||||
#include "Flow.hpp"
|
#include "Flow.hpp"
|
||||||
#include "PrintConfig.hpp"
|
#include "PrintConfig.hpp"
|
||||||
#include "Fill/Lightning/Generator.hpp"
|
#include "Fill/Lightning/Generator.hpp"
|
||||||
|
#include "TreeModelVolumes.hpp"
|
||||||
|
#include "TreeSupport3D.hpp"
|
||||||
|
|
||||||
#ifndef SQ
|
#ifndef SQ
|
||||||
#define SQ(x) ((x)*(x))
|
#define SQ(x) ((x)*(x))
|
||||||
|
@ -26,17 +28,158 @@ struct LayerHeightData
|
||||||
{
|
{
|
||||||
coordf_t print_z = 0;
|
coordf_t print_z = 0;
|
||||||
coordf_t height = 0;
|
coordf_t height = 0;
|
||||||
size_t next_layer_nr = 0;
|
size_t obj_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 obj_layer) : print_z(z), height(h), obj_layer_nr(obj_layer) {}
|
||||||
|
coordf_t bottom_z() {
|
||||||
|
return print_z - height;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TreeNode {
|
enum TreeNodeType {
|
||||||
Vec3f pos;
|
eCircle,
|
||||||
std::vector<int> children; // index of children in the storing vector
|
eSquare,
|
||||||
std::vector<int> parents; // index of parents in the storing vector
|
ePolygon
|
||||||
TreeNode(Point pt, float z) {
|
};
|
||||||
pos = { float(unscale_(pt.x())),float(unscale_(pt.y())),z };
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Represents the metadata of a node in the tree.
|
||||||
|
*/
|
||||||
|
struct SupportNode
|
||||||
|
{
|
||||||
|
static constexpr SupportNode* NO_PARENT = nullptr;
|
||||||
|
|
||||||
|
SupportNode()
|
||||||
|
: distance_to_top(0)
|
||||||
|
, position(Point(0, 0))
|
||||||
|
, obj_layer_nr(0)
|
||||||
|
, support_roof_layers_below(0)
|
||||||
|
, to_buildplate(true)
|
||||||
|
, parent(nullptr)
|
||||||
|
, print_z(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;
|
||||||
|
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 radius_ = 0)
|
||||||
|
: distance_to_top(distance_to_top)
|
||||||
|
, position(position)
|
||||||
|
, obj_layer_nr(obj_layer_nr)
|
||||||
|
, support_roof_layers_below(support_roof_layers_below)
|
||||||
|
, to_buildplate(to_buildplate)
|
||||||
|
, parent(parent)
|
||||||
|
, print_z(print_z_)
|
||||||
|
, height(height_)
|
||||||
|
, dist_mm_to_top(dist_mm_to_top_)
|
||||||
|
, radius(radius_)
|
||||||
|
{
|
||||||
|
if (parent) {
|
||||||
|
parents.push_back(parent);
|
||||||
|
type = parent->type;
|
||||||
|
overhang = parent->overhang;
|
||||||
|
if (dist_mm_to_top == 0)
|
||||||
|
dist_mm_to_top = parent->dist_mm_to_top + parent->height;
|
||||||
|
if (radius == 0 && parent->radius>0)
|
||||||
|
radius = parent->radius + (dist_mm_to_top - parent->dist_mm_to_top) * diameter_angle_scale_factor;
|
||||||
|
parent->child = this;
|
||||||
|
for (auto& neighbor : parent->merged_neighbours) {
|
||||||
|
neighbor->child = this;
|
||||||
|
parents.push_back(neighbor);
|
||||||
|
}
|
||||||
|
is_sharp_tail = parent->is_sharp_tail;
|
||||||
|
skin_direction = parent->skin_direction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG // Clear the delete node's data so if there's invalid access after, we may get a clue by inspecting that node.
|
||||||
|
~SupportNode()
|
||||||
|
{
|
||||||
|
parent = nullptr;
|
||||||
|
merged_neighbours.clear();
|
||||||
|
}
|
||||||
|
#endif // DEBUG
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The number of layers to go to the top of this branch.
|
||||||
|
* Negative value means it's a virtual node between support and overhang, which doesn't need to be extruded.
|
||||||
|
*/
|
||||||
|
int distance_to_top;
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
Point position;
|
||||||
|
Point movement; // movement towards neighbor center or outline
|
||||||
|
mutable double radius = 0.0;
|
||||||
|
mutable double max_move_dist = 0.0;
|
||||||
|
TreeNodeType type = eCircle;
|
||||||
|
bool is_corner = false;
|
||||||
|
bool is_processed = false;
|
||||||
|
bool need_extra_wall = false;
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
* This determines in which direction we should reduce the width of the
|
||||||
|
* branch.
|
||||||
|
*/
|
||||||
|
Point skin_direction;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The number of support roof layers below this one.
|
||||||
|
*
|
||||||
|
* When a contact point is created, it is determined whether the mesh
|
||||||
|
* needs to be supported with support roof or not, since that is a
|
||||||
|
* per-mesh setting. This is stored in this variable in order to track
|
||||||
|
* how far we need to extend that support roof downwards.
|
||||||
|
*/
|
||||||
|
int support_roof_layers_below;
|
||||||
|
int obj_layer_nr;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Whether to try to go towards the build plate.
|
||||||
|
*
|
||||||
|
* If the node is inside the collision areas, it has no choice but to go
|
||||||
|
* towards the model. If it is not inside the collision areas, it must
|
||||||
|
* go towards the build plate to prevent a scar on the surface.
|
||||||
|
*/
|
||||||
|
bool to_buildplate;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The originating node for this one, one layer higher.
|
||||||
|
*
|
||||||
|
* In order to prune branches that can't have any support (because they
|
||||||
|
* can't be on the model and the path to the buildplate isn't clear),
|
||||||
|
* the entire branch needs to be known.
|
||||||
|
*/
|
||||||
|
SupportNode* parent;
|
||||||
|
std::vector<SupportNode*> parents;
|
||||||
|
SupportNode* child = nullptr;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief All neighbours (on the same layer) that where merged into this node.
|
||||||
|
*
|
||||||
|
* In order to prune branches that can't have any support (because they
|
||||||
|
* can't be on the model and the path to the buildplate isn't clear),
|
||||||
|
* the entire branch needs to be known.
|
||||||
|
*/
|
||||||
|
std::list<SupportNode*> merged_neighbours;
|
||||||
|
|
||||||
|
coordf_t print_z;
|
||||||
|
coordf_t height;
|
||||||
|
|
||||||
|
bool operator==(const SupportNode& other) const
|
||||||
|
{
|
||||||
|
return position == other.position;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -54,12 +197,12 @@ public:
|
||||||
*
|
*
|
||||||
* \param xy_distance The required clearance between the model and the
|
* \param xy_distance The required clearance between the model and the
|
||||||
* tree branches.
|
* tree branches.
|
||||||
* \param max_move The maximum allowable movement between nodes on
|
|
||||||
* adjacent layers
|
|
||||||
* \param radius_sample_resolution Sample size used to round requested node radii.
|
* \param radius_sample_resolution Sample size used to round requested node radii.
|
||||||
* \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 xy_distance, coordf_t radius_sample_resolution);
|
||||||
|
~TreeSupportData() {
|
||||||
|
clear_nodes();
|
||||||
|
}
|
||||||
|
|
||||||
TreeSupportData(TreeSupportData&&) = default;
|
TreeSupportData(TreeSupportData&&) = default;
|
||||||
TreeSupportData& operator=(TreeSupportData&&) = default;
|
TreeSupportData& operator=(TreeSupportData&&) = default;
|
||||||
|
@ -98,9 +241,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();
|
||||||
std::vector<LayerHeightData> layer_heights;
|
std::vector<LayerHeightData> layer_heights;
|
||||||
|
|
||||||
std::vector<TreeNode> tree_nodes;
|
std::vector<std::unique_ptr<SupportNode>> contact_nodes;
|
||||||
|
// ExPolygon m_machine_border;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*!
|
/*!
|
||||||
|
@ -146,6 +293,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;
|
||||||
|
@ -154,11 +302,7 @@ public:
|
||||||
*/
|
*/
|
||||||
coordf_t m_xy_distance;
|
coordf_t m_xy_distance;
|
||||||
|
|
||||||
/*!
|
double branch_scale_factor = 1.0; // tan(45 degrees)
|
||||||
* \brief The maximum distance that the centrepoint of a tree branch may
|
|
||||||
* move in consequtive layers
|
|
||||||
*/
|
|
||||||
coordf_t m_max_move;
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Sample resolution for radius values.
|
* \brief Sample resolution for radius values.
|
||||||
|
@ -177,6 +321,8 @@ public:
|
||||||
// union contours of all layers below
|
// union contours of all layers below
|
||||||
std::vector<ExPolygons> m_layer_outlines_below;
|
std::vector<ExPolygons> m_layer_outlines_below;
|
||||||
|
|
||||||
|
std::vector<double> m_max_move_distances;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Caches for the collision, avoidance and internal model polygons
|
* \brief Caches for the collision, avoidance and internal model polygons
|
||||||
* at given radius and layer indices.
|
* at given radius and layer indices.
|
||||||
|
@ -215,6 +361,10 @@ public:
|
||||||
*/
|
*/
|
||||||
TreeSupport(PrintObject& object, const SlicingParameters &slicing_params);
|
TreeSupport(PrintObject& object, const SlicingParameters &slicing_params);
|
||||||
|
|
||||||
|
void move_bounds_to_contact_nodes(std::vector<TreeSupport3D::SupportElements> &move_bounds,
|
||||||
|
PrintObject &print_object,
|
||||||
|
const TreeSupport3D::TreeSupportSettings &config);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Create the areas that need support.
|
* \brief Create the areas that need support.
|
||||||
*
|
*
|
||||||
|
@ -224,180 +374,28 @@ public:
|
||||||
*/
|
*/
|
||||||
void generate();
|
void generate();
|
||||||
|
|
||||||
void detect_overhangs(bool detect_first_sharp_tail_only=false);
|
void detect_overhangs(bool check_support_necessity = false);
|
||||||
|
|
||||||
enum NodeType {
|
SupportNode* create_node(const Point position,
|
||||||
eCircle,
|
const int distance_to_top,
|
||||||
eSquare,
|
const int obj_layer_nr,
|
||||||
ePolygon
|
const int support_roof_layers_below,
|
||||||
};
|
const bool to_buildplate,
|
||||||
|
SupportNode* parent,
|
||||||
/*!
|
coordf_t print_z_,
|
||||||
* \brief Represents the metadata of a node in the tree.
|
coordf_t height_,
|
||||||
*/
|
coordf_t dist_mm_to_top_ = 0,
|
||||||
struct Node
|
coordf_t radius_ = 0)
|
||||||
{
|
{
|
||||||
static constexpr Node* NO_PARENT = nullptr;
|
return m_ts_data->create_node(position, distance_to_top, obj_layer_nr, support_roof_layers_below, to_buildplate, parent, print_z_, height_, dist_mm_to_top_, radius_);
|
||||||
|
|
||||||
Node()
|
|
||||||
: distance_to_top(0)
|
|
||||||
, position(Point(0, 0))
|
|
||||||
, obj_layer_nr(0)
|
|
||||||
, support_roof_layers_below(0)
|
|
||||||
, support_floor_layers_above(0)
|
|
||||||
, to_buildplate(true)
|
|
||||||
, parent(nullptr)
|
|
||||||
, print_z(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;
|
|
||||||
Node(const Point position, const int distance_to_top, const int obj_layer_nr, const int support_roof_layers_below, const bool to_buildplate, Node* parent,
|
|
||||||
coordf_t print_z_, coordf_t height_, coordf_t dist_mm_to_top_=0)
|
|
||||||
: distance_to_top(distance_to_top)
|
|
||||||
, position(position)
|
|
||||||
, obj_layer_nr(obj_layer_nr)
|
|
||||||
, support_roof_layers_below(support_roof_layers_below)
|
|
||||||
, support_floor_layers_above(0)
|
|
||||||
, to_buildplate(to_buildplate)
|
|
||||||
, parent(parent)
|
|
||||||
, print_z(print_z_)
|
|
||||||
, height(height_)
|
|
||||||
, dist_mm_to_top(dist_mm_to_top_)
|
|
||||||
{
|
|
||||||
if (parent) {
|
|
||||||
type = parent->type;
|
|
||||||
overhang = parent->overhang;
|
|
||||||
if (dist_mm_to_top==0)
|
|
||||||
dist_mm_to_top = parent->dist_mm_to_top + parent->height;
|
|
||||||
parent->child = this;
|
|
||||||
for (auto& neighbor : parent->merged_neighbours)
|
|
||||||
neighbor->child = this;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG // Clear the delete node's data so if there's invalid access after, we may get a clue by inspecting that node.
|
|
||||||
~Node()
|
|
||||||
{
|
|
||||||
parent = nullptr;
|
|
||||||
merged_neighbours.clear();
|
|
||||||
}
|
|
||||||
#endif // DEBUG
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief The number of layers to go to the top of this branch.
|
|
||||||
* Negative value means it's a virtual node between support and overhang, which doesn't need to be extruded.
|
|
||||||
*/
|
|
||||||
int distance_to_top;
|
|
||||||
coordf_t dist_mm_to_top = 0; // dist to bottom contact in mm
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief The position of this node on the layer.
|
|
||||||
*/
|
|
||||||
Point position;
|
|
||||||
Point movement; // movement towards neighbor center or outline
|
|
||||||
mutable double radius = 0.0;
|
|
||||||
mutable double max_move_dist = 0.0;
|
|
||||||
NodeType type = eCircle;
|
|
||||||
bool is_merged = false; // this node is generated by merging upper nodes
|
|
||||||
bool is_corner = false;
|
|
||||||
bool is_processed = false;
|
|
||||||
const ExPolygon *overhang = nullptr; // when type==ePolygon, set this value to get original overhang area
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief The direction of the skin lines above the tip of the branch.
|
|
||||||
*
|
|
||||||
* This determines in which direction we should reduce the width of the
|
|
||||||
* branch.
|
|
||||||
*/
|
|
||||||
bool skin_direction;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief The number of support roof layers below this one.
|
|
||||||
*
|
|
||||||
* When a contact point is created, it is determined whether the mesh
|
|
||||||
* needs to be supported with support roof or not, since that is a
|
|
||||||
* per-mesh setting. This is stored in this variable in order to track
|
|
||||||
* how far we need to extend that support roof downwards.
|
|
||||||
*/
|
|
||||||
int support_roof_layers_below;
|
|
||||||
int support_floor_layers_above;
|
|
||||||
int obj_layer_nr;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Whether to try to go towards the build plate.
|
|
||||||
*
|
|
||||||
* If the node is inside the collision areas, it has no choice but to go
|
|
||||||
* towards the model. If it is not inside the collision areas, it must
|
|
||||||
* go towards the build plate to prevent a scar on the surface.
|
|
||||||
*/
|
|
||||||
bool to_buildplate;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief The originating node for this one, one layer higher.
|
|
||||||
*
|
|
||||||
* In order to prune branches that can't have any support (because they
|
|
||||||
* can't be on the model and the path to the buildplate isn't clear),
|
|
||||||
* the entire branch needs to be known.
|
|
||||||
*/
|
|
||||||
Node *parent;
|
|
||||||
Node *child = nullptr;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief All neighbours (on the same layer) that where merged into this node.
|
|
||||||
*
|
|
||||||
* In order to prune branches that can't have any support (because they
|
|
||||||
* can't be on the model and the path to the buildplate isn't clear),
|
|
||||||
* the entire branch needs to be known.
|
|
||||||
*/
|
|
||||||
std::list<Node*> merged_neighbours;
|
|
||||||
|
|
||||||
coordf_t print_z;
|
|
||||||
coordf_t height;
|
|
||||||
|
|
||||||
bool operator==(const Node& other) const
|
|
||||||
{
|
|
||||||
return position == other.position;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SupportParams
|
|
||||||
{
|
|
||||||
Flow first_layer_flow;
|
|
||||||
Flow support_material_flow;
|
|
||||||
Flow support_material_interface_flow;
|
|
||||||
Flow support_material_bottom_interface_flow;
|
|
||||||
coordf_t support_extrusion_width;
|
|
||||||
// Is merging of regions allowed? Could the interface & base support regions be printed with the same extruder?
|
|
||||||
bool can_merge_support_regions;
|
|
||||||
|
|
||||||
coordf_t support_layer_height_min;
|
|
||||||
// coordf_t support_layer_height_max;
|
|
||||||
|
|
||||||
coordf_t gap_xy;
|
|
||||||
|
|
||||||
float base_angle;
|
|
||||||
float interface_angle;
|
|
||||||
coordf_t interface_spacing;
|
|
||||||
coordf_t interface_density;
|
|
||||||
coordf_t support_spacing;
|
|
||||||
coordf_t support_density;
|
|
||||||
|
|
||||||
InfillPattern base_fill_pattern;
|
|
||||||
InfillPattern interface_fill_pattern;
|
|
||||||
InfillPattern contact_fill_pattern;
|
|
||||||
bool with_sheath;
|
|
||||||
const double thresh_big_overhang = SQ(scale_(10));
|
|
||||||
};
|
|
||||||
|
|
||||||
int avg_node_per_layer = 0;
|
int avg_node_per_layer = 0;
|
||||||
float nodes_angle = 0;
|
float nodes_angle = 0;
|
||||||
bool has_overhangs = false;
|
|
||||||
bool has_sharp_tails = false;
|
bool has_sharp_tails = false;
|
||||||
bool has_cantilever = false;
|
bool has_cantilever = false;
|
||||||
double max_cantilever_dist = 0;
|
double max_cantilever_dist = 0;
|
||||||
SupportType support_type;
|
SupportType support_type;
|
||||||
SupportMaterialStyle support_style;
|
|
||||||
|
|
||||||
std::unique_ptr<FillLightning::Generator> generator;
|
std::unique_ptr<FillLightning::Generator> generator;
|
||||||
std::unordered_map<double, size_t> printZ_to_lightninglayer;
|
std::unordered_map<double, size_t> printZ_to_lightninglayer;
|
||||||
|
@ -410,6 +408,10 @@ public:
|
||||||
*/
|
*/
|
||||||
ExPolygon m_machine_border;
|
ExPolygon m_machine_border;
|
||||||
|
|
||||||
|
enum OverhangType { Detected = 0, Enforced, SharpTail };
|
||||||
|
std::map<const ExPolygon*, OverhangType> overhang_types;
|
||||||
|
std::vector<std::pair<Vec3f, Vec3f>> m_vertical_enforcer_points;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*!
|
/*!
|
||||||
* \brief Generator for model collision, avoidance and internal guide volumes
|
* \brief Generator for model collision, avoidance and internal guide volumes
|
||||||
|
@ -417,20 +419,29 @@ private:
|
||||||
* Lazily computes volumes as needed.
|
* Lazily computes volumes as needed.
|
||||||
* \warning This class is NOT currently thread-safe and should not be accessed in OpenMP blocks
|
* \warning This class is NOT currently thread-safe and should not be accessed in OpenMP blocks
|
||||||
*/
|
*/
|
||||||
|
std::vector<std::vector<SupportNode*>> contact_nodes;
|
||||||
std::shared_ptr<TreeSupportData> m_ts_data;
|
std::shared_ptr<TreeSupportData> m_ts_data;
|
||||||
|
std::unique_ptr<TreeSupport3D::TreeModelVolumes> m_model_volumes;
|
||||||
PrintObject *m_object;
|
PrintObject *m_object;
|
||||||
const PrintObjectConfig *m_object_config;
|
const PrintObjectConfig* m_object_config;
|
||||||
SlicingParameters m_slicing_params;
|
SlicingParameters m_slicing_params;
|
||||||
// Various precomputed support parameters to be shared with external functions.
|
// Various precomputed support parameters to be shared with external functions.
|
||||||
SupportParams m_support_params;
|
SupportParameters m_support_params;
|
||||||
size_t m_raft_layers = 0;
|
size_t m_raft_layers = 0; // number of raft layers, including raft base, raft interface, raft gap
|
||||||
size_t m_highest_overhang_layer = 0;
|
size_t m_highest_overhang_layer = 0;
|
||||||
std::vector<std::vector<MinimumSpanningTree>> m_spanning_trees;
|
std::vector<std::vector<MinimumSpanningTree>> m_spanning_trees;
|
||||||
std::vector< std::unordered_map<Line, bool, LineHash>> m_mst_line_x_layer_contour_caches;
|
std::vector< std::unordered_map<Line, bool, LineHash>> m_mst_line_x_layer_contour_caches;
|
||||||
coordf_t MAX_BRANCH_RADIUS = 10.0;
|
float DO_NOT_MOVER_UNDER_MM = 0.0;
|
||||||
coordf_t MAX_BRANCH_RADIUS_FIRST_LAYER = 12.0;
|
coordf_t base_radius = 0.0;
|
||||||
coordf_t MIN_BRANCH_RADIUS = 0.5;
|
const coordf_t MAX_BRANCH_RADIUS = 10.0;
|
||||||
float tree_support_branch_diameter_angle = 5.0;
|
const coordf_t MIN_BRANCH_RADIUS = 0.4;
|
||||||
|
const coordf_t MAX_BRANCH_RADIUS_FIRST_LAYER = 12.0;
|
||||||
|
const coordf_t MIN_BRANCH_RADIUS_FIRST_LAYER = 2.0;
|
||||||
|
double diameter_angle_scale_factor = tan(5.0*M_PI/180.0);
|
||||||
|
// minimum roof area (1 mm^2), area smaller than this value will not have interface
|
||||||
|
const double minimum_roof_area{SQ(scaled<double>(1.))};
|
||||||
|
float top_z_distance = 0.0;
|
||||||
|
|
||||||
bool is_strong = false;
|
bool is_strong = false;
|
||||||
bool is_slim = false;
|
bool is_slim = false;
|
||||||
bool with_infill = false;
|
bool with_infill = false;
|
||||||
|
@ -447,7 +458,7 @@ private:
|
||||||
* save the resulting support polygons to.
|
* save the resulting support polygons to.
|
||||||
* \param contact_nodes The nodes to draw as support.
|
* \param contact_nodes The nodes to draw as support.
|
||||||
*/
|
*/
|
||||||
void draw_circles(const std::vector<std::vector<Node*>>& contact_nodes);
|
void draw_circles();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Drops down the nodes of the tree support towards the build plate.
|
* \brief Drops down the nodes of the tree support towards the build plate.
|
||||||
|
@ -461,18 +472,16 @@ private:
|
||||||
* dropped down. The nodes are dropped to lower layers inside the same
|
* dropped down. The nodes are dropped to lower layers inside the same
|
||||||
* vector of layers.
|
* vector of layers.
|
||||||
*/
|
*/
|
||||||
void drop_nodes(std::vector<std::vector<Node *>> &contact_nodes);
|
void drop_nodes();
|
||||||
|
|
||||||
void smooth_nodes(std::vector<std::vector<Node *>> &contact_nodes);
|
void smooth_nodes();
|
||||||
|
|
||||||
void adjust_layer_heights(std::vector<std::vector<Node*>>& contact_nodes);
|
|
||||||
|
|
||||||
/*! BBS: MusangKing: maximum layer height
|
/*! BBS: MusangKing: maximum layer height
|
||||||
* \brief Optimize the generation of tree support by pre-planning the layer_heights
|
* \brief Optimize the generation of tree support by pre-planning the layer_heights
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
std::vector<LayerHeightData> plan_layer_heights(std::vector<std::vector<Node *>> &contact_nodes);
|
std::vector<LayerHeightData> plan_layer_heights();
|
||||||
/*!
|
/*!
|
||||||
* \brief Creates points where support contacts the model.
|
* \brief Creates points where support contacts the model.
|
||||||
*
|
*
|
||||||
|
@ -486,20 +495,27 @@ private:
|
||||||
* \return For each layer, a list of points where the tree should connect
|
* \return For each layer, a list of points where the tree should connect
|
||||||
* with the model.
|
* with the model.
|
||||||
*/
|
*/
|
||||||
void generate_contact_points(std::vector<std::vector<Node*>>& contact_nodes);
|
void generate_contact_points();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Add a node to the next layer.
|
* \brief Add a node to the next layer.
|
||||||
*
|
*
|
||||||
* If a node is already at that position in the layer, the nodes are merged.
|
* If a node is already at that position in the layer, the nodes are merged.
|
||||||
*/
|
*/
|
||||||
void insert_dropped_node(std::vector<Node*>& nodes_layer, Node* node);
|
void insert_dropped_node(std::vector<SupportNode*>& nodes_layer, SupportNode* node);
|
||||||
void create_tree_support_layers();
|
void create_tree_support_layers();
|
||||||
void generate_toolpaths();
|
void generate_toolpaths();
|
||||||
Polygons spanning_tree_to_polygon(const std::vector<MinimumSpanningTree>& spanning_trees, Polygons layer_contours, int layer_nr);
|
// get unscaled radius of node
|
||||||
Polygons contact_nodes_to_polygon(const std::vector<Node*>& contact_nodes, Polygons layer_contours, int layer_nr, std::vector<double>& radiis, std::vector<bool>& is_interface);
|
|
||||||
coordf_t calc_branch_radius(coordf_t base_radius, size_t layers_to_top, size_t tip_layers, double diameter_angle_scale_factor);
|
coordf_t calc_branch_radius(coordf_t base_radius, size_t layers_to_top, size_t tip_layers, double diameter_angle_scale_factor);
|
||||||
coordf_t calc_branch_radius(coordf_t base_radius, coordf_t mm_to_top, double diameter_angle_scale_factor);
|
// get unscaled radius(mm) of node based on the distance mm to top
|
||||||
|
coordf_t calc_branch_radius(coordf_t base_radius, coordf_t mm_to_top, double diameter_angle_scale_factor, bool use_min_distance=true);
|
||||||
|
coordf_t calc_radius(coordf_t mm_to_top);
|
||||||
|
coordf_t get_radius(const SupportNode* node);
|
||||||
|
ExPolygons get_avoidance(coordf_t radius, size_t obj_layer_nr);
|
||||||
|
// layer's expolygon expanded by radius+m_xy_distance
|
||||||
|
ExPolygons get_collision(coordf_t radius, size_t layer_nr);
|
||||||
|
// get Polygons instead of ExPolygons
|
||||||
|
Polygons get_collision_polys(coordf_t radius, size_t layer_nr);
|
||||||
|
|
||||||
// similar to SupportMaterial::trim_support_layers_by_object
|
// similar to SupportMaterial::trim_support_layers_by_object
|
||||||
Polygons get_trim_support_regions(
|
Polygons get_trim_support_regions(
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -47,8 +47,6 @@ struct SlicingParameters;
|
||||||
namespace TreeSupport3D
|
namespace TreeSupport3D
|
||||||
{
|
{
|
||||||
|
|
||||||
// The number of vertices in each circle.
|
|
||||||
static constexpr const size_t SUPPORT_TREE_CIRCLE_RESOLUTION = 25;
|
|
||||||
|
|
||||||
struct AreaIncreaseSettings
|
struct AreaIncreaseSettings
|
||||||
{
|
{
|
||||||
|
@ -139,6 +137,10 @@ struct SupportElementStateBits {
|
||||||
|
|
||||||
struct SupportElementState : public SupportElementStateBits
|
struct SupportElementState : public SupportElementStateBits
|
||||||
{
|
{
|
||||||
|
int type = 0;
|
||||||
|
coordf_t radius = 0;
|
||||||
|
float print_z = 0;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief The layer this support elements wants reach
|
* \brief The layer this support elements wants reach
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -17,10 +17,10 @@
|
||||||
|
|
||||||
namespace Slic3r
|
namespace Slic3r
|
||||||
{
|
{
|
||||||
|
// The number of vertices in each circle.
|
||||||
|
static constexpr const size_t SUPPORT_TREE_CIRCLE_RESOLUTION = 25;
|
||||||
namespace TreeSupport3D
|
namespace TreeSupport3D
|
||||||
{
|
{
|
||||||
|
|
||||||
using LayerIndex = int;
|
using LayerIndex = int;
|
||||||
|
|
||||||
enum class InterfacePreference
|
enum class InterfacePreference
|
||||||
|
@ -42,8 +42,8 @@ struct TreeSupportMeshGroupSettings {
|
||||||
// const std::vector<unsigned int> printing_extruders = print_object.object_extruders();
|
// const std::vector<unsigned int> printing_extruders = print_object.object_extruders();
|
||||||
|
|
||||||
// Support must be enabled and set to Tree style.
|
// Support must be enabled and set to Tree style.
|
||||||
assert(config.enable_support || config.enforce_support_layers > 0);
|
//assert(config.support_material);
|
||||||
assert(is_tree(config.support_type));
|
//assert(config.support_material_style == smsTree || config.support_material_style == smsOrganic);
|
||||||
|
|
||||||
// Calculate maximum external perimeter width over all printing regions, taking into account the default layer height.
|
// Calculate maximum external perimeter width over all printing regions, taking into account the default layer height.
|
||||||
coordf_t external_perimeter_width = 0.;
|
coordf_t external_perimeter_width = 0.;
|
||||||
|
@ -69,28 +69,20 @@ struct TreeSupportMeshGroupSettings {
|
||||||
0;
|
0;
|
||||||
this->support_material_buildplate_only = config.support_on_build_plate_only;
|
this->support_material_buildplate_only = config.support_on_build_plate_only;
|
||||||
this->support_xy_distance = scaled<coord_t>(config.support_object_xy_distance.value);
|
this->support_xy_distance = scaled<coord_t>(config.support_object_xy_distance.value);
|
||||||
|
this->support_xy_distance_1st_layer = scaled<coord_t>(config.support_object_first_layer_gap.value);
|
||||||
// Separation of interfaces, it is likely smaller than support_xy_distance.
|
// Separation of interfaces, it is likely smaller than support_xy_distance.
|
||||||
this->support_xy_distance_overhang = std::min(this->support_xy_distance, scaled<coord_t>(0.5 * external_perimeter_width));
|
this->support_xy_distance_overhang = std::min(this->support_xy_distance, scaled<coord_t>(0.5 * external_perimeter_width));
|
||||||
this->support_top_distance = scaled<coord_t>(slicing_params.gap_support_object);
|
this->support_top_distance = scaled<coord_t>(slicing_params.gap_support_object);
|
||||||
this->support_bottom_distance = scaled<coord_t>(slicing_params.gap_object_support);
|
this->support_bottom_distance = scaled<coord_t>(slicing_params.gap_object_support);
|
||||||
// this->support_interface_skip_height =
|
|
||||||
// this->support_infill_angles =
|
|
||||||
this->support_roof_enable = config.support_interface_top_layers.value > 0;
|
this->support_roof_enable = config.support_interface_top_layers.value > 0;
|
||||||
this->support_roof_layers = this->support_roof_enable ? config.support_interface_top_layers.value : 0;
|
this->support_roof_layers = config.support_interface_top_layers.value;
|
||||||
this->support_floor_enable = config.support_interface_top_layers.value > 0 && config.support_interface_bottom_layers.value > 0;
|
this->support_floor_enable = config.support_interface_bottom_layers.value > 0;
|
||||||
this->support_floor_layers = this->support_floor_enable ? config.support_interface_bottom_layers.value : 0;
|
this->support_floor_layers = config.support_interface_bottom_layers.value;
|
||||||
// this->minimum_roof_area =
|
|
||||||
// this->support_roof_angles =
|
|
||||||
this->support_roof_pattern = config.support_interface_pattern;
|
this->support_roof_pattern = config.support_interface_pattern;
|
||||||
this->support_pattern = config.support_base_pattern;
|
this->support_pattern = config.support_base_pattern;
|
||||||
this->support_line_spacing = scaled<coord_t>(config.support_base_pattern_spacing.value);
|
this->support_line_spacing = scaled<coord_t>(config.support_base_pattern_spacing.value);
|
||||||
// this->support_bottom_offset =
|
this->support_wall_count = std::max(1, config.tree_support_wall_count.value); // at least 1 wall for organic tree support
|
||||||
// this->support_wall_count = config.support_material_with_sheath ? 1 : 0;
|
|
||||||
this->support_wall_count = 1;
|
|
||||||
this->support_roof_line_distance = scaled<coord_t>(config.support_interface_spacing.value) + this->support_roof_line_width;
|
this->support_roof_line_distance = scaled<coord_t>(config.support_interface_spacing.value) + this->support_roof_line_width;
|
||||||
// this->minimum_support_area =
|
|
||||||
// this->minimum_bottom_area =
|
|
||||||
// this->support_offset =
|
|
||||||
this->support_tree_branch_distance = scaled<coord_t>(config.tree_support_branch_distance_organic.value);
|
this->support_tree_branch_distance = scaled<coord_t>(config.tree_support_branch_distance_organic.value);
|
||||||
this->support_tree_angle = std::clamp<double>(config.tree_support_branch_angle_organic * M_PI / 180., 0., 0.5 * M_PI - EPSILON);
|
this->support_tree_angle = std::clamp<double>(config.tree_support_branch_angle_organic * M_PI / 180., 0., 0.5 * M_PI - EPSILON);
|
||||||
this->support_tree_angle_slow = std::clamp<double>(config.tree_support_angle_slow * M_PI / 180., 0., this->support_tree_angle - EPSILON);
|
this->support_tree_angle_slow = std::clamp<double>(config.tree_support_angle_slow * M_PI / 180., 0., this->support_tree_angle - EPSILON);
|
||||||
|
@ -99,26 +91,6 @@ struct TreeSupportMeshGroupSettings {
|
||||||
this->support_tree_top_rate = config.tree_support_top_rate.value; // percent
|
this->support_tree_top_rate = config.tree_support_top_rate.value; // percent
|
||||||
// this->support_tree_tip_diameter = this->support_line_width;
|
// this->support_tree_tip_diameter = this->support_line_width;
|
||||||
this->support_tree_tip_diameter = std::clamp(scaled<coord_t>(config.tree_support_tip_diameter.value), (coord_t)0, this->support_tree_branch_diameter);
|
this->support_tree_tip_diameter = std::clamp(scaled<coord_t>(config.tree_support_tip_diameter.value), (coord_t)0, this->support_tree_branch_diameter);
|
||||||
|
|
||||||
std::cout << "\n---------------\n"
|
|
||||||
<< "layer_height: " << layer_height << "\nresolution: " << resolution << "\nmin_feature_size: " << min_feature_size
|
|
||||||
<< "\nsupport_angle: " << support_angle << "\nconfig.support_threshold_angle: " << config.support_threshold_angle << "\nsupport_line_width: " << support_line_width
|
|
||||||
<< "\nsupport_roof_line_width: " << support_roof_line_width << "\nsupport_bottom_enable: " << support_bottom_enable
|
|
||||||
<< "\nsupport_bottom_height: " << support_bottom_height
|
|
||||||
<< "\nsupport_material_buildplate_only: " << support_material_buildplate_only
|
|
||||||
<< "\nsupport_xy_distance: " << support_xy_distance << "\nsupport_xy_distance_overhang: " << support_xy_distance_overhang
|
|
||||||
<< "\nsupport_top_distance: " << support_top_distance << "\nsupport_bottom_distance: " << support_bottom_distance
|
|
||||||
<< "\nsupport_roof_enable: " << support_roof_enable << "\nsupport_roof_layers: " << support_roof_layers
|
|
||||||
<< "\nsupport_floor_enable: " << support_floor_enable << "\nsupport_floor_layers: " << support_floor_layers
|
|
||||||
<< "\nsupport_roof_pattern: " << support_roof_pattern << "\nsupport_pattern: " << support_pattern
|
|
||||||
<< "\nsupport_line_spacing: " << support_line_spacing << "\nsupport_wall_count: " << support_wall_count
|
|
||||||
<< "\nsupport_roof_line_distance: " << support_roof_line_distance
|
|
||||||
<< "\nsupport_tree_branch_distance: " << support_tree_branch_distance
|
|
||||||
<< "\nsupport_tree_angle_slow: " << support_tree_angle_slow
|
|
||||||
<< "\nsupport_tree_branch_diameter: " << support_tree_branch_diameter
|
|
||||||
<< "\nsupport_tree_branch_diameter_angle: " << support_tree_branch_diameter_angle
|
|
||||||
<< "\nsupport_tree_top_rate: " << support_tree_top_rate << "\nsupport_tree_tip_diameter: " << support_tree_tip_diameter
|
|
||||||
<< "\n---------------\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
|
@ -158,6 +130,7 @@ struct TreeSupportMeshGroupSettings {
|
||||||
// Distance of the support structure from the print in the X/Y directions.
|
// Distance of the support structure from the print in the X/Y directions.
|
||||||
// minimum: 0, maximum warning: 1.5 * machine_nozzle_tip_outer_diameter
|
// minimum: 0, maximum warning: 1.5 * machine_nozzle_tip_outer_diameter
|
||||||
coord_t support_xy_distance { scaled<coord_t>(0.7) };
|
coord_t support_xy_distance { scaled<coord_t>(0.7) };
|
||||||
|
coord_t support_xy_distance_1st_layer { scaled<coord_t>(0.7) };
|
||||||
// Minimum Support X/Y Distance
|
// Minimum Support X/Y Distance
|
||||||
// Distance of the support structure from the overhang in the X/Y directions.
|
// Distance of the support structure from the overhang in the X/Y directions.
|
||||||
// minimum_value: 0, minimum warning": support_xy_distance - support_line_width * 2, maximum warning: support_xy_distance
|
// minimum_value: 0, minimum warning": support_xy_distance - support_line_width * 2, maximum warning: support_xy_distance
|
||||||
|
@ -766,6 +739,17 @@ private:
|
||||||
std::mutex m_mutex_layer_storage;
|
std::mutex m_mutex_layer_storage;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class LineStatus
|
||||||
|
{
|
||||||
|
INVALID,
|
||||||
|
TO_MODEL,
|
||||||
|
TO_MODEL_GRACIOUS,
|
||||||
|
TO_MODEL_GRACIOUS_SAFE,
|
||||||
|
TO_BP,
|
||||||
|
TO_BP_SAFE
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace TreeSupport3D
|
} // namespace TreeSupport3D
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
|
@ -957,7 +957,6 @@ inline std::pair<SlabLines, SlabLines> slice_slabs_make_lines(
|
||||||
}
|
}
|
||||||
slice_facet_with_slabs<true>(vertices, indices, face_idx, neighbors, edge_ids, num_edges, zs, lines_top, lines_mutex_top);
|
slice_facet_with_slabs<true>(vertices, indices, face_idx, neighbors, edge_ids, num_edges, zs, lines_top, lines_mutex_top);
|
||||||
}
|
}
|
||||||
// BBS: add vertical faces option
|
|
||||||
if (bottom && (fo == FaceOrientation::Down || fo == FaceOrientation::Degenerate)) {
|
if (bottom && (fo == FaceOrientation::Down || fo == FaceOrientation::Degenerate)) {
|
||||||
Vec3i32 neighbors = face_neighbors[face_idx];
|
Vec3i32 neighbors = face_neighbors[face_idx];
|
||||||
// Reset neighborship of this triangle in case the other triangle is oriented backwards from this one.
|
// Reset neighborship of this triangle in case the other triangle is oriented backwards from this one.
|
||||||
|
@ -2063,6 +2062,7 @@ void slice_mesh_slabs(
|
||||||
const Transform3d &trafo,
|
const Transform3d &trafo,
|
||||||
std::vector<Polygons> *out_top,
|
std::vector<Polygons> *out_top,
|
||||||
std::vector<Polygons> *out_bottom,
|
std::vector<Polygons> *out_bottom,
|
||||||
|
std::vector<std::pair<Vec3f, Vec3f>> *vertical_points,
|
||||||
std::function<void()> throw_on_cancel)
|
std::function<void()> throw_on_cancel)
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(debug) << "slice_mesh_slabs to polygons";
|
BOOST_LOG_TRIVIAL(debug) << "slice_mesh_slabs to polygons";
|
||||||
|
@ -2133,6 +2133,11 @@ void slice_mesh_slabs(
|
||||||
// Is the triangle vertical or degenerate?
|
// Is the triangle vertical or degenerate?
|
||||||
assert(d == 0);
|
assert(d == 0);
|
||||||
fo = fa == fb || fa == fc || fb == fc ? FaceOrientation::Degenerate : FaceOrientation::Vertical;
|
fo = fa == fb || fa == fc || fb == fc ? FaceOrientation::Degenerate : FaceOrientation::Vertical;
|
||||||
|
if(vertical_points && fo==FaceOrientation::Vertical)
|
||||||
|
{
|
||||||
|
Vec3f normal = (fb - fa).cross(fc - fa).normalized();
|
||||||
|
vertical_points->push_back({ (fa + fb + fc) / 3,normal });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
face_orientation[&tri - mesh.indices.data()] = fo;
|
face_orientation[&tri - mesh.indices.data()] = fo;
|
||||||
}
|
}
|
||||||
|
@ -2297,7 +2302,7 @@ void project_mesh(
|
||||||
{
|
{
|
||||||
std::vector<Polygons> top, bottom;
|
std::vector<Polygons> top, bottom;
|
||||||
std::vector<float> zs { -1e10, 1e10 };
|
std::vector<float> zs { -1e10, 1e10 };
|
||||||
slice_mesh_slabs(mesh, zs, trafo, out_top ? &top : nullptr, out_bottom ? &bottom : nullptr, throw_on_cancel);
|
slice_mesh_slabs(mesh, zs, trafo, out_top ? &top : nullptr, out_bottom ? &bottom : nullptr, nullptr, throw_on_cancel);
|
||||||
if (out_top)
|
if (out_top)
|
||||||
*out_top = std::move(top.front());
|
*out_top = std::move(top.front());
|
||||||
if (out_bottom)
|
if (out_bottom)
|
||||||
|
@ -2311,7 +2316,7 @@ Polygons project_mesh(
|
||||||
{
|
{
|
||||||
std::vector<Polygons> top, bottom;
|
std::vector<Polygons> top, bottom;
|
||||||
std::vector<float> zs { -1e10, 1e10 };
|
std::vector<float> zs { -1e10, 1e10 };
|
||||||
slice_mesh_slabs(mesh, zs, trafo, &top, &bottom, throw_on_cancel);
|
slice_mesh_slabs(mesh, zs, trafo, &top, &bottom, nullptr, throw_on_cancel);
|
||||||
return union_(top.front(), bottom.back());
|
return union_(top.front(), bottom.back());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -107,6 +107,7 @@ void slice_mesh_slabs(
|
||||||
const Transform3d &trafo,
|
const Transform3d &trafo,
|
||||||
std::vector<Polygons> *out_top,
|
std::vector<Polygons> *out_top,
|
||||||
std::vector<Polygons> *out_bottom,
|
std::vector<Polygons> *out_bottom,
|
||||||
|
std::vector<std::pair<Vec3f, Vec3f>> *vertical_points,
|
||||||
std::function<void()> throw_on_cancel);
|
std::function<void()> throw_on_cancel);
|
||||||
|
|
||||||
// Project mesh upwards pointing surfaces / downwards pointing surfaces into 2D polygons.
|
// Project mesh upwards pointing surfaces / downwards pointing surfaces into 2D polygons.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -426,7 +426,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
|
||||||
auto support_type = config->opt_enum<SupportType>("support_type");
|
auto support_type = config->opt_enum<SupportType>("support_type");
|
||||||
auto support_style = config->opt_enum<SupportMaterialStyle>("support_style");
|
auto support_style = config->opt_enum<SupportMaterialStyle>("support_style");
|
||||||
std::set<int> enum_set_normal = { smsDefault, smsGrid, smsSnug };
|
std::set<int> enum_set_normal = { smsDefault, smsGrid, smsSnug };
|
||||||
std::set<int> enum_set_tree = { smsDefault, smsTreeSlim, smsTreeStrong, smsTreeHybrid, smsOrganic };
|
std::set<int> enum_set_tree = { smsDefault, smsTreeSlim, smsTreeStrong, smsTreeHybrid, smsTreeOrganic };
|
||||||
auto & set = is_tree(support_type) ? enum_set_tree : enum_set_normal;
|
auto & set = is_tree(support_type) ? enum_set_tree : enum_set_normal;
|
||||||
if (set.find(support_style) == set.end()) {
|
if (set.find(support_style) == set.end()) {
|
||||||
DynamicPrintConfig new_conf = *config;
|
DynamicPrintConfig new_conf = *config;
|
||||||
|
@ -600,14 +600,14 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
||||||
"support_interface_pattern", "support_interface_top_layers", "support_interface_bottom_layers",
|
"support_interface_pattern", "support_interface_top_layers", "support_interface_bottom_layers",
|
||||||
"bridge_no_support", "max_bridge_length", "support_top_z_distance", "support_bottom_z_distance",
|
"bridge_no_support", "max_bridge_length", "support_top_z_distance", "support_bottom_z_distance",
|
||||||
"support_type", "support_on_build_plate_only", "support_critical_regions_only","support_interface_not_for_body",
|
"support_type", "support_on_build_plate_only", "support_critical_regions_only","support_interface_not_for_body",
|
||||||
"support_object_xy_distance"/*, "independent_support_layer_height"*/})
|
"support_object_xy_distance","support_object_first_layer_gap"/*, "independent_support_layer_height"*/})
|
||||||
toggle_field(el, have_support_material);
|
toggle_field(el, have_support_material);
|
||||||
toggle_field("support_threshold_angle", have_support_material && is_auto(support_type));
|
toggle_field("support_threshold_angle", have_support_material && is_auto(support_type));
|
||||||
toggle_field("support_threshold_overlap", config->opt_int("support_threshold_angle") == 0 && have_support_material && is_auto(support_type));
|
toggle_field("support_threshold_overlap", config->opt_int("support_threshold_angle") == 0 && have_support_material && is_auto(support_type));
|
||||||
//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);
|
||||||
bool support_is_normal_tree = support_is_tree && support_style != smsOrganic &&
|
bool support_is_normal_tree = support_is_tree && support_style != smsTreeOrganic &&
|
||||||
// Orca: use organic as default
|
// Orca: use organic as default
|
||||||
support_style != smsDefault;
|
support_style != smsDefault;
|
||||||
bool support_is_organic = support_is_tree && !support_is_normal_tree;
|
bool support_is_organic = support_is_tree && !support_is_normal_tree;
|
||||||
|
@ -615,10 +615,10 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
||||||
for (auto el : {"tree_support_branch_angle", "tree_support_branch_distance", "tree_support_branch_diameter" })
|
for (auto el : {"tree_support_branch_angle", "tree_support_branch_distance", "tree_support_branch_diameter" })
|
||||||
toggle_line(el, support_is_normal_tree);
|
toggle_line(el, support_is_normal_tree);
|
||||||
// settings specific to normal trees
|
// settings specific to normal trees
|
||||||
for (auto el : {"tree_support_wall_count", "tree_support_auto_brim", "tree_support_brim_width", "tree_support_adaptive_layer_height"})
|
for (auto el : {"tree_support_auto_brim", "tree_support_brim_width", "tree_support_adaptive_layer_height"})
|
||||||
toggle_line(el, support_is_normal_tree);
|
toggle_line(el, support_is_normal_tree);
|
||||||
// settings specific to organic trees
|
// settings specific to organic trees
|
||||||
for (auto el : {"tree_support_branch_angle_organic", "tree_support_branch_distance_organic", "tree_support_branch_diameter_organic","tree_support_angle_slow","tree_support_tip_diameter", "tree_support_top_rate", "tree_support_branch_diameter_angle", "tree_support_branch_diameter_double_wall"})
|
for (auto el : {"tree_support_branch_angle_organic", "tree_support_branch_distance_organic", "tree_support_branch_diameter_organic","tree_support_angle_slow","tree_support_tip_diameter", "tree_support_top_rate", "tree_support_branch_diameter_angle"})
|
||||||
toggle_line(el, support_is_organic);
|
toggle_line(el, support_is_organic);
|
||||||
|
|
||||||
toggle_field("tree_support_brim_width", support_is_tree && !config->opt_bool("tree_support_auto_brim"));
|
toggle_field("tree_support_brim_width", support_is_tree && !config->opt_bool("tree_support_auto_brim"));
|
||||||
|
|
|
@ -2125,7 +2125,8 @@ bool GUI_App::OnInit()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return on_init_inner();
|
return on_init_inner();
|
||||||
} catch (const std::exception&) {
|
} catch (const std::exception& e) {
|
||||||
|
BOOST_LOG_TRIVIAL(fatal) << "OnInit Got Fatal error: " << e.what();
|
||||||
generic_exception_handle();
|
generic_exception_handle();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,10 +90,11 @@ std::map<std::string, std::vector<SimpleSettingData>> SettingsFactory::OBJECT_C
|
||||||
{ L("Support"), {{"brim_type", "",1},{"brim_width", "",2},{"brim_object_gap", "",3},
|
{ L("Support"), {{"brim_type", "",1},{"brim_width", "",2},{"brim_object_gap", "",3},
|
||||||
{"enable_support", "",4},{"support_type", "",5},{"support_threshold_angle", "",6}, {"support_threshold_overlap", "",6}, {"support_on_build_plate_only", "",7},
|
{"enable_support", "",4},{"support_type", "",5},{"support_threshold_angle", "",6}, {"support_threshold_overlap", "",6}, {"support_on_build_plate_only", "",7},
|
||||||
{"support_filament", "",8},{"support_interface_filament", "",9},{"support_expansion", "",24},{"support_style", "",25},
|
{"support_filament", "",8},{"support_interface_filament", "",9},{"support_expansion", "",24},{"support_style", "",25},
|
||||||
{"tree_support_brim_width", "",26}, {"tree_support_branch_angle", "",10},{"tree_support_branch_angle_organic","",10}, {"tree_support_wall_count", "",11},//tree support
|
{"tree_support_brim_width", "",26}, {"tree_support_branch_angle", "",10},{"tree_support_branch_angle_organic","",10}, {"tree_support_wall_count", "",11},{"tree_support_branch_diameter_angle", "",11},//tree support
|
||||||
{"support_top_z_distance", "",13},{"support_bottom_z_distance", "",12},{"support_base_pattern", "",14},{"support_base_pattern_spacing", "",15},
|
{"support_top_z_distance", "",13},{"support_bottom_z_distance", "",12},{"support_base_pattern", "",14},{"support_base_pattern_spacing", "",15},
|
||||||
{"support_interface_top_layers", "",16},{"support_interface_bottom_layers", "",17},{"support_interface_spacing", "",18},{"support_bottom_interface_spacing", "",19},
|
{"support_interface_top_layers", "",16},{"support_interface_bottom_layers", "",17},{"support_interface_spacing", "",18},{"support_bottom_interface_spacing", "",19},
|
||||||
{"support_object_xy_distance", "",20}, {"bridge_no_support", "",21},{"max_bridge_length", "",22},{"support_critical_regions_only", "",23},{"support_remove_small_overhang","",27}
|
{"support_object_xy_distance", "",20}, {"bridge_no_support", "",21},{"max_bridge_length", "",22},{"support_critical_regions_only", "",23},{"support_remove_small_overhang","",27},
|
||||||
|
{"support_object_first_layer_gap","",28}
|
||||||
}},
|
}},
|
||||||
{ L("Speed"), {{"support_speed", "",12}, {"support_interface_speed", "",13}
|
{ L("Speed"), {{"support_speed", "",12}, {"support_interface_speed", "",13}
|
||||||
}}
|
}}
|
||||||
|
@ -155,6 +156,7 @@ std::vector<SimpleSettingData> SettingsFactory::get_visible_options(const std::s
|
||||||
"tree_support_wall_count",
|
"tree_support_wall_count",
|
||||||
//support
|
//support
|
||||||
"support_top_z_distance", "support_base_pattern", "support_base_pattern_spacing", "support_interface_top_layers", "support_interface_bottom_layers", "support_interface_spacing", "support_bottom_interface_spacing", "support_object_xy_distance",
|
"support_top_z_distance", "support_base_pattern", "support_base_pattern_spacing", "support_interface_top_layers", "support_interface_bottom_layers", "support_interface_spacing", "support_bottom_interface_spacing", "support_object_xy_distance",
|
||||||
|
"support_object_first_layer_gap",
|
||||||
//adhesion
|
//adhesion
|
||||||
"brim_type", "brim_width", "brim_object_gap", "raft_layers"
|
"brim_type", "brim_width", "brim_object_gap", "raft_layers"
|
||||||
};*/
|
};*/
|
||||||
|
|
|
@ -1496,50 +1496,13 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
|
||||||
m_config_manipulation.apply(m_config, &new_conf);
|
m_config_manipulation.apply(m_config, &new_conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// BBS popup a message to ask the user to set optimum parameters for tree support
|
|
||||||
if (opt_key == "support_type" || opt_key == "support_style") {
|
|
||||||
if (is_tree_slim(m_config->opt_enum<SupportType>("support_type"), m_config->opt_enum<SupportMaterialStyle>("support_style")) &&
|
|
||||||
!(m_config->opt_float("support_top_z_distance") == 0 && m_config->opt_int("support_interface_top_layers") == 0 && m_config->opt_int("tree_support_wall_count") == 2)) {
|
|
||||||
wxString msg_text = _L("We have added an experimental style \"Tree Slim\" that features smaller support volume but weaker strength.\n"
|
|
||||||
"We recommend using it with: 0 interface layers, 0 top distance, 2 walls.");
|
|
||||||
msg_text += "\n\n" + _L("Change these settings automatically? \n"
|
|
||||||
"Yes - Change these settings automatically\n"
|
|
||||||
"No - Do not change these settings for me");
|
|
||||||
MessageDialog dialog(wxGetApp().plater(), msg_text, "Suggestion", wxICON_WARNING | wxYES | wxNO);
|
|
||||||
DynamicPrintConfig new_conf = *m_config;
|
|
||||||
if (dialog.ShowModal() == wxID_YES) {
|
|
||||||
new_conf.set_key_value("support_top_z_distance", new ConfigOptionFloat(0));
|
|
||||||
new_conf.set_key_value("support_interface_top_layers", new ConfigOptionInt(0));
|
|
||||||
new_conf.set_key_value("tree_support_wall_count", new ConfigOptionInt(2));
|
|
||||||
m_config_manipulation.apply(m_config, &new_conf);
|
|
||||||
}
|
|
||||||
wxGetApp().plater()->update();
|
|
||||||
} else if ((m_config->opt_enum<SupportType>("support_type")==stTreeAuto && (m_config->opt_enum<SupportMaterialStyle>("support_style")==smsTreeStrong || m_config->opt_enum<SupportMaterialStyle>("support_style") == smsTreeHybrid)) &&
|
|
||||||
!((m_config->opt_float("support_top_z_distance") >=0.1 || is_support_filament(m_config->opt_int("support_interface_filament") - 1))
|
|
||||||
&& m_config->opt_int("support_interface_top_layers") >1) ) {
|
|
||||||
wxString msg_text = _L("For \"Tree Strong\" and \"Tree Hybrid\" styles, we recommend the following settings: at least 2 interface layers, at least 0.1mm top z distance or using support materials on interface.");
|
|
||||||
msg_text += "\n\n" + _L("Change these settings automatically? \n"
|
|
||||||
"Yes - Change these settings automatically\n"
|
|
||||||
"No - Do not change these settings for me");
|
|
||||||
MessageDialog dialog(wxGetApp().plater(), msg_text, "Suggestion", wxICON_WARNING | wxYES | wxNO);
|
|
||||||
DynamicPrintConfig new_conf = *m_config;
|
|
||||||
if (dialog.ShowModal() == wxID_YES) {
|
|
||||||
if (!is_support_filament(m_config->opt_int("support_interface_filament") - 1) && m_config->opt_float("support_top_z_distance") < 0.1)
|
|
||||||
new_conf.set_key_value("support_top_z_distance", new ConfigOptionFloat(0.2));
|
|
||||||
new_conf.set_key_value("support_interface_top_layers", new ConfigOptionInt(2));
|
|
||||||
m_config_manipulation.apply(m_config, &new_conf);
|
|
||||||
}
|
|
||||||
wxGetApp().plater()->update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// BBS popup a message to ask the user to set optimum parameters for support interface if support materials are used
|
// BBS popup a message to ask the user to set optimum parameters for support interface if support materials are used
|
||||||
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 +1511,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);
|
||||||
}
|
}
|
||||||
|
@ -2262,6 +2225,7 @@ void TabPrint::build()
|
||||||
optgroup = page->new_optgroup(L("Advanced"), L"param_advanced");
|
optgroup = page->new_optgroup(L("Advanced"), L"param_advanced");
|
||||||
optgroup->append_single_option_line("support_top_z_distance", "support#top-z-distance");
|
optgroup->append_single_option_line("support_top_z_distance", "support#top-z-distance");
|
||||||
optgroup->append_single_option_line("support_bottom_z_distance", "support#bottom-z-distance");
|
optgroup->append_single_option_line("support_bottom_z_distance", "support#bottom-z-distance");
|
||||||
|
optgroup->append_single_option_line("tree_support_wall_count");
|
||||||
optgroup->append_single_option_line("support_base_pattern", "support#base-pattern");
|
optgroup->append_single_option_line("support_base_pattern", "support#base-pattern");
|
||||||
optgroup->append_single_option_line("support_base_pattern_spacing", "support#base-pattern");
|
optgroup->append_single_option_line("support_base_pattern_spacing", "support#base-pattern");
|
||||||
optgroup->append_single_option_line("support_angle");
|
optgroup->append_single_option_line("support_angle");
|
||||||
|
@ -2274,8 +2238,9 @@ void TabPrint::build()
|
||||||
//optgroup->append_single_option_line("support_interface_loop_pattern");
|
//optgroup->append_single_option_line("support_interface_loop_pattern");
|
||||||
|
|
||||||
optgroup->append_single_option_line("support_object_xy_distance", "support");
|
optgroup->append_single_option_line("support_object_xy_distance", "support");
|
||||||
|
optgroup->append_single_option_line("support_object_first_layer_gap", "support");
|
||||||
optgroup->append_single_option_line("bridge_no_support", "support#base-pattern");
|
optgroup->append_single_option_line("bridge_no_support", "support#base-pattern");
|
||||||
optgroup->append_single_option_line("max_bridge_length", "support#base-pattern");
|
optgroup->append_single_option_line("max_bridge_length", "support#tree-support-only-options");
|
||||||
optgroup->append_single_option_line("independent_support_layer_height", "support");
|
optgroup->append_single_option_line("independent_support_layer_height", "support");
|
||||||
|
|
||||||
optgroup = page->new_optgroup(L("Tree supports"), L"param_support_tree");
|
optgroup = page->new_optgroup(L("Tree supports"), L"param_support_tree");
|
||||||
|
@ -2289,8 +2254,6 @@ void TabPrint::build()
|
||||||
optgroup->append_single_option_line("tree_support_branch_angle", "support#tree-support-only-options");
|
optgroup->append_single_option_line("tree_support_branch_angle", "support#tree-support-only-options");
|
||||||
optgroup->append_single_option_line("tree_support_branch_angle_organic", "support#tree-support-only-options");
|
optgroup->append_single_option_line("tree_support_branch_angle_organic", "support#tree-support-only-options");
|
||||||
optgroup->append_single_option_line("tree_support_angle_slow");
|
optgroup->append_single_option_line("tree_support_angle_slow");
|
||||||
optgroup->append_single_option_line("tree_support_branch_diameter_double_wall");
|
|
||||||
optgroup->append_single_option_line("tree_support_wall_count");
|
|
||||||
optgroup->append_single_option_line("tree_support_adaptive_layer_height");
|
optgroup->append_single_option_line("tree_support_adaptive_layer_height");
|
||||||
optgroup->append_single_option_line("tree_support_auto_brim");
|
optgroup->append_single_option_line("tree_support_auto_brim");
|
||||||
optgroup->append_single_option_line("tree_support_brim_width");
|
optgroup->append_single_option_line("tree_support_brim_width");
|
||||||
|
@ -2458,7 +2421,7 @@ void TabPrint::toggle_options()
|
||||||
if (auto choice = dynamic_cast<Choice*>(field)) {
|
if (auto choice = dynamic_cast<Choice*>(field)) {
|
||||||
auto def = print_config_def.get("support_style");
|
auto def = print_config_def.get("support_style");
|
||||||
std::vector<int> enum_set_normal = {smsDefault, smsGrid, smsSnug };
|
std::vector<int> enum_set_normal = {smsDefault, smsGrid, smsSnug };
|
||||||
std::vector<int> enum_set_tree = { smsDefault, smsTreeSlim, smsTreeStrong, smsTreeHybrid, smsOrganic };
|
std::vector<int> enum_set_tree = { smsDefault, smsTreeSlim, smsTreeStrong, smsTreeHybrid, smsTreeOrganic };
|
||||||
auto & set = is_tree(support_type) ? enum_set_tree : enum_set_normal;
|
auto & set = is_tree(support_type) ? enum_set_tree : enum_set_normal;
|
||||||
auto & opt = const_cast<ConfigOptionDef &>(field->m_opt);
|
auto & opt = const_cast<ConfigOptionDef &>(field->m_opt);
|
||||||
auto cb = dynamic_cast<ComboBox *>(choice->window);
|
auto cb = dynamic_cast<ComboBox *>(choice->window);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue