mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-07 23:17:35 -06:00
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:
parent
f00bdfeca8
commit
532dcae37a
10 changed files with 130 additions and 230 deletions
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2959,36 +2927,6 @@ SupportGeneratorLayersPtr PrintObjectSupportMaterial::raft_and_intermediate_supp
|
|||
for (size_t i = 0; i < top_contacts.size(); ++i)
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
@ -86,20 +83,24 @@ struct SupportParameters {
|
|||
// Object is printed with the same extruder as the support.
|
||||
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;
|
||||
|
@ -115,9 +116,7 @@ struct SupportParameters {
|
|||
object_config.support_interface_pattern == smipConcentric ?
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -379,7 +379,7 @@ public:
|
|||
|
||||
|
||||
int avg_node_per_layer = 0;
|
||||
float nodes_angle = 0;
|
||||
float nodes_angle = 0;
|
||||
bool has_sharp_tails = false;
|
||||
bool has_cantilever = false;
|
||||
double max_cantilever_dist = 0;
|
||||
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
@ -40,18 +40,18 @@ struct TreeSupportMeshGroupSettings {
|
|||
const PrintObjectConfig &config = print_object.config();
|
||||
const SlicingParameters &slicing_params = print_object.slicing_parameters();
|
||||
// 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.;
|
||||
for (size_t region_id = 0; region_id < print_object.num_printing_regions(); ++ region_id) {
|
||||
const PrintRegion ®ion = print_object.printing_region(region_id);
|
||||
external_perimeter_width = std::max<coordf_t>(external_perimeter_width, region.flow(print_object, frExternalPerimeter, config.layer_height).width());
|
||||
}
|
||||
|
||||
|
||||
this->layer_height = scaled<coord_t>(config.layer_height.value);
|
||||
this->resolution = scaled<coord_t>(print_config.resolution.value);
|
||||
// Arache feature
|
||||
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue