ENH: add rectilinear interface pattern for organic support

1. add rectilinear interface pattern for organic support
    jira: STUDIO-7181
2. add tree support optgroup

Change-Id: I94882bc34a61c6adc06b8ecbc9f2323f9b039aac
(cherry picked from commit a8142ab3f37e0bd140a31a7e635b8475f471d7e3)
(cherry picked from commit 69cf816b9431bc21ca0187c7db1148e2d2e898ab)
This commit is contained in:
Arthur 2024-05-28 20:11:45 +08:00 committed by Noisyfox
parent f00bdfeca8
commit 532dcae37a
10 changed files with 130 additions and 230 deletions

View file

@ -309,16 +309,16 @@ set(lisbslic3r_sources
Support/SupportLayer.hpp
Support/SupportMaterial.cpp
Support/SupportMaterial.hpp
Support/SupportParameters.hpp
Support/SupportSpotsGenerator.cpp
Support/SupportSpotsGenerator.hpp
Support/TreeSupport.hpp
Support/TreeSupport.cpp
Support/TreeSupport3D.cpp
Support/TreeSupport3D.hpp
Support/TreeSupportCommon.hpp
Support/TreeModelVolumes.cpp
Support/TreeSupport3D.cpp
Support/TreeModelVolumes.hpp
Support/TreeModelVolumes.cpp
Support/TreeSupportCommon.hpp
Support/SupportParameters.hpp
PrincipalComponents2D.cpp
PrincipalComponents2D.hpp
MinimumSpanningTree.hpp

View file

@ -56,7 +56,7 @@ Fill* Fill::new_from_type(const InfillPattern type)
case ipOctagramSpiral: return new FillOctagramSpiral();
case ipAdaptiveCubic: 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();
// BBS: for internal solid infill only
case ipConcentricInternal: return new FillConcentricInternal();

View file

@ -329,22 +329,6 @@ static Polygons contours_simplified(const Vec2i32 &grid_size, const double pixel
}
#endif // SUPPORT_USE_AGG_RASTERIZER
static std::string get_svg_filename(std::string layer_nr_or_z, std::string tag = "bbl_ts")
{
static bool rand_init = false;
if (!rand_init) {
srand(time(NULL));
rand_init = true;
}
int rand_num = rand() % 1000000;
//makedir("./SVG");
std::string prefix = "./SVG/";
std::string suffix = ".svg";
return prefix + tag + "_" + layer_nr_or_z /*+ "_" + std::to_string(rand_num)*/ + suffix;
}
PrintObjectSupportMaterial::PrintObjectSupportMaterial(const PrintObject *object, const SlicingParameters &slicing_params) :
m_print_config (&object->print()->config()),
m_object_config (&object->config()),
@ -567,18 +551,6 @@ void PrintObjectSupportMaterial::generate(PrintObject &object)
}
#endif /* SLIC3R_DEBUG */
#if 0 // #ifdef SLIC3R_DEBUG
// check bounds
std::ofstream out;
out.open("./SVG/ns_support_layers.txt");
if (out.is_open()) {
out << "### Support Layers ###" << std::endl;
for (auto& i : object.support_layers()) {
out << i->print_z << std::endl;
}
}
#endif /* SLIC3R_DEBUG */
// Generate the actual toolpaths and save them into each layer.
generate_support_toolpaths(object.support_layers(), *m_object_config, m_support_params, m_slicing_params, raft_layers, bottom_contacts, top_contacts, intermediate_layers, interface_layers, base_interface_layers);
@ -2245,10 +2217,6 @@ SupportGeneratorLayersPtr PrintObjectSupportMaterial::top_contact_layers(
layer->sharp_tails.push_back(expoly);
layer->sharp_tails_height.push_back( accum_height );
append(overhangs_per_layers[layer_nr], overhang);
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
SVG svg(get_svg_filename(std::to_string(layer->print_z), "sharp_tail"), object.bounding_box());
if (svg.is_opened()) svg.draw(overhang, "yellow");
#endif
}
}
@ -2960,36 +2928,6 @@ SupportGeneratorLayersPtr PrintObjectSupportMaterial::raft_and_intermediate_supp
assert(top_contacts[i]->height > 0.);
#endif /* _DEBUG */
#if 0 // #ifdef SLIC3R_DEBUG
// check bounds
std::ofstream out;
out.open("./SVG/ns_bounds.txt");
if (out.is_open()) {
if (!top_contacts.empty()) {
out << "### Top Contacts ###" << std::endl;
for (auto& t : top_contacts) {
out << t->print_z << std::endl;
}
}
if (!bottom_contacts.empty()) {
out << "### Bottome Contacts ###" << std::endl;
for (auto& b : bottom_contacts) {
out << b->print_z << std::endl;
}
}
if (!intermediate_layers.empty()) {
out << "### Intermediate Layers ###" << std::endl;
for (auto& i : intermediate_layers) {
out << i->print_z << std::endl;
}
}
out << "### Slice Layers ###" << std::endl;
for (size_t j = 0; j < object.layers().size(); ++j) {
out << object.layers()[j]->print_z << std::endl;
}
}
#endif /* SLIC3R_DEBUG */
return intermediate_layers;
}

View file

@ -5,11 +5,8 @@
#include "../Flow.hpp"
namespace Slic3r {
class PrintObject;
enum InfillPattern : int;
struct SupportParameters {
SupportParameters() = default;
SupportParameters(const PrintObject &object)
{
const PrintConfig &print_config = object.print()->config();
@ -87,19 +84,23 @@ struct SupportParameters {
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();
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_density = std::min(1., this->support_material_flow.spacing() / support_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() / this->support_spacing);
if (object_config.support_interface_top_layers.value == 0) {
// No interface layers allowed, print everything with the base support pattern.
this->interface_spacing = this->support_spacing;
this->interface_density = this->support_density;
}
SupportMaterialPattern support_pattern = object_config.support_base_pattern;
this->with_sheath = /*is_tree(object_config.support_type) &&*/ object_config.tree_support_wall_count > 0;
this->with_sheath = object_config.tree_support_wall_count > 0;
this->base_fill_pattern =
support_pattern == smpHoneycomb ? ipHoneycomb :
this->support_density > 0.95 || this->with_sheath ? ipRectilinear : ipSupportBase;
@ -116,8 +117,6 @@ struct SupportParameters {
ipConcentric :
(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_base = 0.f;
this->raft_angle_interface = 0.f;
@ -215,11 +214,13 @@ struct SupportParameters {
float base_angle;
float interface_angle;
coordf_t interface_spacing;
coordf_t support_expansion=0;
// Density of the top / bottom interface and contact layers.
coordf_t interface_density;
// Density of the raft interface and contact layers.
coordf_t raft_interface_density;
coordf_t support_spacing;
// Density of the base support layers.
coordf_t support_density;
SupportMaterialStyle support_style = smsDefault;
@ -235,7 +236,7 @@ struct SupportParameters {
// Shall the sparse (base) layers be printed with a single perimeter line (sheath) for robustness?
bool with_sheath;
// 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>(3.0)) * M_PI;;
float raft_angle_1st_layer;
float raft_angle_base;

View file

@ -1,23 +1,27 @@
#include <math.h>
#include "MinimumSpanningTree.hpp"
#include "TreeSupport.hpp"
#include "Print.hpp"
#include "Layer.hpp"
#include "ClipperUtils.hpp"
#include "Fill/FillBase.hpp"
#include "Fill/FillBase.hpp"
#include "Fill/FillConcentric.hpp"
#include "CurveAnalyzer.hpp"
#include "SVG.hpp"
#include "ShortestPath.hpp"
#include "I18N.hpp"
#include "Layer.hpp"
#include "MinimumSpanningTree.hpp"
#include "Print.hpp"
#include "ShortestPath.hpp"
#include "SupportCommon.hpp"
#include "SVG.hpp"
#include "TreeSupportCommon.hpp"
#include "TreeSupport.hpp"
#include "TreeSupport3D.hpp"
#include <libnest2d/backends/libslic3r/geometries.hpp>
#include <libnest2d/placers/nfpplacer.hpp>
#include "TreeSupport3D.hpp"
#include <boost/log/trivial.hpp>
#include <tbb/concurrent_vector.h>
#include <tbb/concurrent_unordered_set.h>
#include <tbb/blocked_range.h>
#include <tbb/concurrent_unordered_set.h>
#include <tbb/concurrent_vector.h>
#include <tbb/parallel_for.h>
#include <tbb/parallel_for_each.h>
@ -1646,28 +1650,25 @@ void TreeSupport::generate()
m_ts_data = m_object->alloc_tree_support_preview_cache();
m_ts_data->is_slim = is_slim;
// Generate contact points of tree support
std::vector<std::vector<SupportNode*>> contact_nodes(m_object->layers().size());
std::vector<TreeSupport3D::SupportElements> move_bounds(m_highest_overhang_layer + 1);
profiler.stage_start(STAGE_GENERATE_CONTACT_NODES);
m_object->print()->set_status(56, _u8L("Support: generate contact points"));
generate_contact_points(contact_nodes);
generate_contact_points();
profiler.stage_finish(STAGE_GENERATE_CONTACT_NODES);
//Drop nodes to lower layers.
profiler.stage_start(STAGE_DROP_DOWN_NODES);
m_object->print()->set_status(60, _u8L("Generating support"));
drop_nodes(contact_nodes);
drop_nodes();
profiler.stage_finish(STAGE_DROP_DOWN_NODES);
smooth_nodes(contact_nodes); // , tree_support_3d_config);
smooth_nodes();// , tree_support_3d_config);
//Generate support areas.
profiler.stage_start(STAGE_DRAW_CIRCLES);
m_object->print()->set_status(65, _u8L("Generating support"));
draw_circles(contact_nodes);
draw_circles();
profiler.stage_finish(STAGE_DRAW_CIRCLES);
@ -1714,7 +1715,6 @@ coordf_t TreeSupport::calc_branch_radius(coordf_t base_radius, coordf_t mm_to_to
{
radius = mm_to_top;// this is a 45 degree tip
}
radius = std::max(radius, MIN_BRANCH_RADIUS);
radius = std::min(radius, MAX_BRANCH_RADIUS);
// if have interface layers, radius should be larger
@ -1876,7 +1876,7 @@ Polygons TreeSupport::get_trim_support_regions(
return polygons_trimming;
}
void TreeSupport::draw_circles(const std::vector<std::vector<SupportNode*>>& contact_nodes)
void TreeSupport::draw_circles()
{
const PrintObjectConfig &config = m_object->config();
const Print* print = m_object->print();
@ -1980,11 +1980,11 @@ void TreeSupport::draw_circles(const std::vector<std::vector<SupportNode*>>& con
}
};
BOOST_LOG_TRIVIAL(debug) << "circles at layer " << layer_nr << " contact nodes size=" << contact_nodes[layer_nr].size();
BOOST_LOG_TRIVIAL(debug) << "circles at layer " << layer_nr << " contact nodes size=" << curr_layer_nodes.size();
//Draw the support areas and add the roofs appropriately to the support roof instead of normal areas.
ts_layer->lslices.reserve(contact_nodes[layer_nr].size());
ts_layer->lslices.reserve(curr_layer_nodes.size());
ExPolygons area_poly; // the polygon node area which will be printed as normal support
for (const SupportNode* p_node : contact_nodes[layer_nr])
for (const SupportNode* p_node : curr_layer_nodes)
{
if (print->canceled())
break;
@ -2366,7 +2366,7 @@ void TreeSupport::draw_circles(const std::vector<std::vector<SupportNode*>>& con
double SupportNode::diameter_angle_scale_factor;
void TreeSupport::drop_nodes(std::vector<std::vector<SupportNode*>>& contact_nodes)
void TreeSupport::drop_nodes()
{
const PrintObjectConfig &config = m_object->config();
// Use Minimum Spanning Tree to connect the points on each layer and move them while dropping them down.
@ -2405,7 +2405,7 @@ void TreeSupport::drop_nodes(std::vector<std::vector<SupportNode*>>& contact_nod
return move_dist;
};
m_ts_data->layer_heights = plan_layer_heights(contact_nodes);
m_ts_data->layer_heights = plan_layer_heights();
std::vector<LayerHeightData> &layer_heights = m_ts_data->layer_heights;
if (layer_heights.empty()) return;
@ -2468,7 +2468,6 @@ void TreeSupport::drop_nodes(std::vector<std::vector<SupportNode*>>& contact_nod
coordf_t height_next = layer_heights[layer_nr_next].height;
std::deque<std::pair<size_t, SupportNode*>> unsupported_branch_leaves; // All nodes that are leaves on this layer that would result in unsupported ('mid-air') branches.
const Layer* ts_layer = m_object->get_support_layer(layer_nr);
m_object->print()->set_status(60 + int(10 * (1 - float(layer_nr) / contact_nodes.size())), _u8L("Generating support"));// (boost::format(_u8L("Support: propagate branches at layer %d")) % layer_nr).str());
@ -2731,7 +2730,7 @@ void TreeSupport::drop_nodes(std::vector<std::vector<SupportNode*>>& contact_nod
// 1. do not merge neighbors under 5mm
// 2. Only merge node with single neighbor in distance between [max_move_distance, 10mm/layer_height]
float dist2_to_first_neighbor = neighbours.empty() ? 0 : vsize2_with_unscale(neighbours[0] - node.position);
if (ts_layer->print_z > DO_NOT_MOVER_UNDER_MM &&
if (node.print_z > DO_NOT_MOVER_UNDER_MM &&
(neighbours.size() > 1 || (neighbours.size() == 1 && dist2_to_first_neighbor >= max_move_distance2))) // Only nodes that aren't about to collapse.
{
// Move towards the average position of all neighbours.
@ -2747,7 +2746,7 @@ void TreeSupport::drop_nodes(std::vector<std::vector<SupportNode*>>& contact_nod
coordf_t branch_bottom_radius = calc_branch_radius(branch_radius, node.dist_mm_to_top + node.print_z, diameter_angle_scale_factor);
coordf_t neighbour_bottom_radius = calc_branch_radius(branch_radius, neighbour_node->dist_mm_to_top + neighbour_node->print_z, diameter_angle_scale_factor);
double max_converge_distance = tan_angle * (ts_layer->print_z - DO_NOT_MOVER_UNDER_MM) + std::max(branch_bottom_radius, neighbour_bottom_radius);
double max_converge_distance = tan_angle * (p_node->print_z - DO_NOT_MOVER_UNDER_MM) + std::max(branch_bottom_radius, neighbour_bottom_radius);
if (dist2_to_neighbor > max_converge_distance * max_converge_distance) continue;
if (is_line_cut_by_contour(node.position, neighbour)) continue;
@ -2892,7 +2891,7 @@ void TreeSupport::drop_nodes(std::vector<std::vector<SupportNode*>>& contact_nod
BOOST_LOG_TRIVIAL(debug) << "after m_avoidance_cache.size()=" << m_ts_data->m_avoidance_cache.size();
}
void TreeSupport::smooth_nodes(std::vector<std::vector<SupportNode *>> &contact_nodes)
void TreeSupport::smooth_nodes()
{
for (int layer_nr = 0; layer_nr < contact_nodes.size(); layer_nr++) {
std::vector<SupportNode *> &curr_layer_nodes = contact_nodes[layer_nr];
@ -2963,7 +2962,7 @@ void TreeSupport::smooth_nodes(std::vector<std::vector<SupportNode *>> &contact_
}
}
std::vector<LayerHeightData> TreeSupport::plan_layer_heights(std::vector<std::vector<SupportNode *>> &contact_nodes)
std::vector<LayerHeightData> TreeSupport::plan_layer_heights()
{
std::vector<LayerHeightData> layer_heights(contact_nodes.size());
std::map<int, std::pair<coordf_t,coordf_t>> bounds; // layer_nr:(print_z, height)
@ -3061,7 +3060,7 @@ std::vector<LayerHeightData> TreeSupport::plan_layer_heights(std::vector<std::ve
return layer_heights;
}
void TreeSupport::generate_contact_points(std::vector<std::vector<SupportNode*>>& contact_nodes)
void TreeSupport::generate_contact_points()
{
const PrintObjectConfig &config = m_object->config();
const coordf_t point_spread = scale_(config.tree_support_branch_distance.value);
@ -3119,8 +3118,11 @@ void TreeSupport::generate_contact_points(std::vector<std::vector<SupportNode*>>
// fix bug of generating support for very thin objects
if (m_object->layers().size() <= z_distance_top_layers + 1)
return;
//if (m_object->support_layer_count() <= m_raft_layers)
// return;
contact_nodes.clear();
contact_nodes.resize(m_object->layers().size());
tbb::spin_mutex mtx;
int nonempty_layers = 0;
tbb::concurrent_vector<Slic3r::Vec3f> all_nodes;

View file

@ -405,11 +405,11 @@ private:
* Lazily computes volumes as needed.
* \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::unique_ptr<TreeSupport3D::TreeModelVolumes> m_model_volumes;
PrintObject *m_object;
const PrintObjectConfig *m_object_config;
const PrintObjectConfig* m_object_config;
SlicingParameters m_slicing_params;
// Various precomputed support parameters to be shared with external functions.
SupportParameters m_support_params;
@ -441,7 +441,7 @@ private:
* save the resulting support polygons to.
* \param contact_nodes The nodes to draw as support.
*/
void draw_circles(const std::vector<std::vector<SupportNode*>>& contact_nodes);
void draw_circles();
/*!
* \brief Drops down the nodes of the tree support towards the build plate.
@ -455,16 +455,16 @@ private:
* dropped down. The nodes are dropped to lower layers inside the same
* vector of layers.
*/
void drop_nodes(std::vector<std::vector<SupportNode*>>& contact_nodes);
void drop_nodes();
void smooth_nodes(std::vector<std::vector<SupportNode*>>& contact_nodes);
void smooth_nodes();
/*! BBS: MusangKing: maximum layer height
* \brief Optimize the generation of tree support by pre-planning the layer_heights
*
*/
std::vector<LayerHeightData> plan_layer_heights(std::vector<std::vector<SupportNode*>>& contact_nodes);
std::vector<LayerHeightData> plan_layer_heights();
/*!
* \brief Creates points where support contacts the model.
*
@ -478,7 +478,7 @@ private:
* \return For each layer, a list of points where the tree should connect
* with the model.
*/
void generate_contact_points(std::vector<std::vector<SupportNode*>>& contact_nodes);
void generate_contact_points();
/*!
* \brief Add a node to the next layer.

View file

@ -7,22 +7,22 @@
// CuraEngine is released under the terms of the AGPLv3 or higher.
#include "TreeSupport3D.hpp"
#include "../AABBTreeIndirect.hpp"
#include "../BuildVolume.hpp"
#include "../ClipperUtils.hpp"
#include "../EdgeGrid.hpp"
#include "../Fill/Fill.hpp"
#include "../Layer.hpp"
#include "../Print.hpp"
#include "../MultiPoint.hpp"
#include "../Polygon.hpp"
#include "../Polyline.hpp"
#include "../MutablePolygon.hpp"
#include "TreeSupportCommon.hpp"
#include "AABBTreeIndirect.hpp"
#include "AABBTreeLines.hpp"
#include "BuildVolume.hpp"
#include "ClipperUtils.hpp"
#include "EdgeGrid.hpp"
#include "Fill/Fill.hpp"
#include "Layer.hpp"
#include "Print.hpp"
#include "MultiPoint.hpp"
#include "Polygon.hpp"
#include "Polyline.hpp"
#include "MutablePolygon.hpp"
#include "SupportCommon.hpp"
#include "TriangleMeshSlicer.hpp"
#include "TreeSupport.hpp"
#include "libslic3r.h"
#include "I18N.hpp"
#include <cassert>
#include <chrono>
@ -49,7 +49,11 @@
#include <openvdb/tools/VolumeToSpheres.h>
#endif // TREE_SUPPORT_ORGANIC_NUDGE_NEW
// #define TREESUPPORT_DEBUG_SVG
#ifndef _L
#define _L(s) Slic3r::I18N::translate(s)
#endif
//#define TREESUPPORT_DEBUG_SVG
namespace Slic3r
{
@ -57,16 +61,6 @@ namespace Slic3r
namespace TreeSupport3D
{
enum class LineStatus
{
INVALID,
TO_MODEL,
TO_MODEL_GRACIOUS,
TO_MODEL_GRACIOUS_SAFE,
TO_BP,
TO_BP_SAFE
};
using LineInformation = std::vector<std::pair<Point, LineStatus>>;
using LineInformations = std::vector<LineInformation>;
using namespace std::literals;
@ -363,6 +357,28 @@ static std::vector<std::pair<TreeSupportSettings, std::vector<size_t>>> group_me
return max_layer;
}
// picked from convert_lines_to_internal()
[[nodiscard]] LineStatus get_avoidance_status(const Point& p, coord_t radius, LayerIndex layer_idx,
const TreeModelVolumes& volumes, const TreeSupportSettings& config)
{
const bool min_xy_dist = config.xy_distance > config.xy_min_distance;
LineStatus type = LineStatus::INVALID;
if (!contains(volumes.getAvoidance(radius, layer_idx, TreeModelVolumes::AvoidanceType::FastSafe, false, min_xy_dist), p))
type = LineStatus::TO_BP_SAFE;
else if (!contains(volumes.getAvoidance(radius, layer_idx, TreeModelVolumes::AvoidanceType::Fast, false, min_xy_dist), p))
type = LineStatus::TO_BP;
else if (config.support_rests_on_model && !contains(volumes.getAvoidance(radius, layer_idx, TreeModelVolumes::AvoidanceType::FastSafe, true, min_xy_dist), p))
type = LineStatus::TO_MODEL_GRACIOUS_SAFE;
else if (config.support_rests_on_model && !contains(volumes.getAvoidance(radius, layer_idx, TreeModelVolumes::AvoidanceType::Fast, true, min_xy_dist), p))
type = LineStatus::TO_MODEL_GRACIOUS;
else if (config.support_rests_on_model && !contains(volumes.getCollision(radius, layer_idx, min_xy_dist), p))
type = LineStatus::TO_MODEL;
return type;
}
/*!
* \brief Converts a Polygons object representing a line into the internal format.
*
@ -1942,7 +1958,7 @@ static void increase_areas_one_layer(
inc_wo_collision.clear();
if (!settings.no_error) {
// ERROR CASE
// if the area becomes for whatever reason something that clipper sees as a line, offset would stop working, so ensure that even if if wrongly would be a line, it still actually has an area that can be increased
// if the area becomes for whatever reason something that clipper sees as a line, offset would stop working, so ensure that even if it would be a line wrongly, it still actually has an area that can be increased
Polygons lines_offset = offset(to_polylines(parent.influence_area), scaled<float>(0.005), jtMiter, 1.2);
Polygons base_error_area = union_(parent.influence_area, lines_offset);
result = increase_single_area(volumes, config, settings, layer_idx, parent,
@ -3321,7 +3337,7 @@ static void organic_smooth_branches_avoid_collisions(
* \param storage The data storage where the mesh data is gotten from and
* where the resulting support areas are stored.
*/
static void generate_support_areas(Print &print, const BuildVolume &build_volume, const std::vector<size_t> &print_object_ids, std::function<void()> throw_on_cancel)
static void generate_support_areas(Print &print, TreeSupport* tree_support, const BuildVolume &build_volume, const std::vector<size_t> &print_object_ids, std::function<void()> throw_on_cancel)
{
// Settings with the indexes of meshes that use these settings.
std::vector<std::pair<TreeSupportSettings, std::vector<size_t>>> grouped_meshes = group_meshes(print, print_object_ids);
@ -3985,7 +4001,7 @@ void generate_tree_support_3D(PrintObject &print_object, TreeSupport* tree_suppo
std::transform(bedpts.begin(), bedpts.end(), std::back_inserter(bedptsf), [](const Point &p) { return unscale(p); });
BuildVolume build_volume{ bedptsf, tree_support->m_print_config->printable_height };
TreeSupport3D::generate_support_areas(*print_object.print(), build_volume, { idx }, throw_on_cancel);
TreeSupport3D::generate_support_areas(*print_object.print(), tree_support, build_volume, { idx }, throw_on_cancel);
}
} // namespace Slic3r

View file

@ -47,8 +47,6 @@ struct SlicingParameters;
namespace TreeSupport3D
{
// The number of vertices in each circle.
static constexpr const size_t SUPPORT_TREE_CIRCLE_RESOLUTION = 25;
struct AreaIncreaseSettings
{

View file

@ -17,10 +17,10 @@
namespace Slic3r
{
// The number of vertices in each circle.
static constexpr const size_t SUPPORT_TREE_CIRCLE_RESOLUTION = 25;
namespace TreeSupport3D
{
using LayerIndex = int;
enum class InterfacePreference
@ -42,8 +42,8 @@ struct TreeSupportMeshGroupSettings {
// const std::vector<unsigned int> printing_extruders = print_object.object_extruders();
// Support must be enabled and set to Tree style.
assert(config.enable_support || config.enforce_support_layers > 0);
assert(is_tree(config.support_type));
//assert(config.support_material);
//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.
coordf_t external_perimeter_width = 0.;
@ -74,24 +74,15 @@ struct TreeSupportMeshGroupSettings {
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_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_layers = this->support_roof_enable ? config.support_interface_top_layers.value : 0;
this->support_floor_enable = config.support_interface_top_layers.value > 0 && config.support_interface_bottom_layers.value > 0;
this->support_floor_layers = this->support_floor_enable ? config.support_interface_bottom_layers.value : 0;
// this->minimum_roof_area =
// this->support_roof_angles =
this->support_roof_layers = config.support_interface_top_layers.value;
this->support_floor_enable = config.support_interface_bottom_layers.value > 0;
this->support_floor_layers = config.support_interface_bottom_layers.value;
this->support_roof_pattern = config.support_interface_pattern;
this->support_pattern = config.support_base_pattern;
this->support_line_spacing = scaled<coord_t>(config.support_base_pattern_spacing.value);
// this->support_bottom_offset =
// this->support_wall_count = config.support_material_with_sheath ? 1 : 0;
this->support_wall_count = 1;
this->support_wall_count = std::max(1, config.tree_support_wall_count.value); // at least 1 wall for organic tree support
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_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);
@ -100,26 +91,6 @@ struct TreeSupportMeshGroupSettings {
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 = 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";
}
/*********************************************************************/
@ -768,6 +739,17 @@ private:
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 Slic3r

View file

@ -1496,43 +1496,6 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
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
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