FIX: empty layers and dangling hybrid support
1. fix possible empty layers (caused by continues walls) 2. fix normal node may be absorbed in drop_nodes in "tree hybrid" 3. popup message to ask the user to select best parameters for tree strong and tree hybrid. 4. auto select lightning infill for tree hybrid. Change-Id: I7d172887a9b0e4f268267684e83fc02dc7ec6a0c (cherry picked from commit bc6d130e86c252d7fc1f84c4df7da95050dd5d51)
This commit is contained in:
parent
3f9c74c86e
commit
58aaa94fc7
|
@ -245,7 +245,7 @@ static void draw_contours_and_nodes_to_svg
|
||||||
|
|
||||||
// draw layer nodes
|
// draw layer nodes
|
||||||
svg.draw(layer_pts, "green", coord_t(scale_(0.1)));
|
svg.draw(layer_pts, "green", coord_t(scale_(0.1)));
|
||||||
|
#if 0
|
||||||
// lower layer points
|
// lower layer points
|
||||||
layer_pts.clear();
|
layer_pts.clear();
|
||||||
for (TreeSupport::Node *node : lower_layer_nodes) {
|
for (TreeSupport::Node *node : lower_layer_nodes) {
|
||||||
|
@ -260,6 +260,7 @@ static void draw_contours_and_nodes_to_svg
|
||||||
layer_pts.push_back(node->parent->position);
|
layer_pts.push_back(node->parent->position);
|
||||||
}
|
}
|
||||||
svg.draw(layer_pts, "blue", coord_t(scale_(0.1)));
|
svg.draw(layer_pts, "blue", coord_t(scale_(0.1)));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_layer_mst
|
static void draw_layer_mst
|
||||||
|
@ -685,6 +686,7 @@ TreeSupport::TreeSupport(PrintObject& object, const SlicingParameters &slicing_p
|
||||||
m_raft_layers = slicing_params.base_raft_layers + slicing_params.interface_raft_layers;
|
m_raft_layers = slicing_params.base_raft_layers + slicing_params.interface_raft_layers;
|
||||||
|
|
||||||
SupportMaterialPattern support_pattern = m_object_config->support_base_pattern;
|
SupportMaterialPattern support_pattern = m_object_config->support_base_pattern;
|
||||||
|
if (m_object_config->support_style == smsTreeHybrid && support_pattern == smpDefault) support_pattern = smpLightning;
|
||||||
m_support_params.base_fill_pattern =
|
m_support_params.base_fill_pattern =
|
||||||
support_pattern == smpLightning ? ipLightning :
|
support_pattern == smpLightning ? ipLightning :
|
||||||
support_pattern == smpHoneycomb ? ipHoneycomb :
|
support_pattern == smpHoneycomb ? ipHoneycomb :
|
||||||
|
@ -700,6 +702,8 @@ TreeSupport::TreeSupport(PrintObject& object, const SlicingParameters &slicing_p
|
||||||
is_slim = is_tree_slim(m_object_config->support_type, m_object_config->support_style);
|
is_slim = is_tree_slim(m_object_config->support_type, m_object_config->support_style);
|
||||||
MAX_BRANCH_RADIUS = is_slim ? 5.0 : 10.0;
|
MAX_BRANCH_RADIUS = is_slim ? 5.0 : 10.0;
|
||||||
tree_support_branch_diameter_angle = 5.0;//is_slim ? 10.0 : 5.0;
|
tree_support_branch_diameter_angle = 5.0;//is_slim ? 10.0 : 5.0;
|
||||||
|
// by default tree support needs no infill, unless it's tree hybrid which contains normal nodes.
|
||||||
|
with_infill = support_pattern != smpNone && support_pattern != smpDefault;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1301,7 +1305,8 @@ static void _make_loops(ExtrusionEntitiesPtr& loops_entities, ExPolygons &suppor
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw connected loops
|
// draw connected loops
|
||||||
if (wall_count > 1 && wall_count<5) {
|
if (/*wall_count > 1 && wall_count<5*/0) {
|
||||||
|
// TODO this method may drop some contours
|
||||||
wall_count = std::min(wall_count, loops.size());
|
wall_count = std::min(wall_count, loops.size());
|
||||||
Polylines polylines;
|
Polylines polylines;
|
||||||
polylines.push_back(Polyline());
|
polylines.push_back(Polyline());
|
||||||
|
@ -1418,9 +1423,7 @@ void TreeSupport::generate_toolpaths()
|
||||||
coordf_t support_extrusion_width = m_support_params.support_extrusion_width;
|
coordf_t support_extrusion_width = m_support_params.support_extrusion_width;
|
||||||
coordf_t nozzle_diameter = print_config.nozzle_diameter.get_at(object_config.support_filament - 1);
|
coordf_t nozzle_diameter = print_config.nozzle_diameter.get_at(object_config.support_filament - 1);
|
||||||
coordf_t layer_height = object_config.layer_height.value;
|
coordf_t layer_height = object_config.layer_height.value;
|
||||||
|
|
||||||
const size_t wall_count = object_config.tree_support_wall_count.value;
|
const size_t wall_count = object_config.tree_support_wall_count.value;
|
||||||
const bool with_infill = object_config.support_base_pattern != smpNone && object_config.support_base_pattern != smpDefault;
|
|
||||||
|
|
||||||
// coconut: use same intensity settings as SupportMaterial.cpp
|
// coconut: use same intensity settings as SupportMaterial.cpp
|
||||||
auto m_support_material_interface_flow = support_material_interface_flow(m_object, float(m_slicing_params.layer_height));
|
auto m_support_material_interface_flow = support_material_interface_flow(m_object, float(m_slicing_params.layer_height));
|
||||||
|
@ -1593,7 +1596,7 @@ void TreeSupport::generate_toolpaths()
|
||||||
// base_areas
|
// base_areas
|
||||||
filler_support->spacing = support_flow.spacing();
|
filler_support->spacing = support_flow.spacing();
|
||||||
Flow flow = (layer_id == 0 && m_raft_layers == 0) ? m_object->print()->brim_flow() : support_flow;
|
Flow flow = (layer_id == 0 && m_raft_layers == 0) ? m_object->print()->brim_flow() : support_flow;
|
||||||
if (area_group.dist_to_top < 10 && !with_infill) {
|
if (area_group.dist_to_top < 10 && !with_infill && m_object_config->support_style!=smsTreeHybrid) {
|
||||||
// at least 2 walls for the top tips
|
// at least 2 walls for the top tips
|
||||||
make_perimeter_and_inner_brim(ts_layer->support_fills.entities, poly, std::max(wall_count, size_t(2)), flow, erSupportMaterial);
|
make_perimeter_and_inner_brim(ts_layer->support_fills.entities, poly, std::max(wall_count, size_t(2)), flow, erSupportMaterial);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1883,8 +1886,7 @@ Polygons TreeSupport::contact_nodes_to_polygon(const std::vector<Node*>& contact
|
||||||
|
|
||||||
void TreeSupport::generate_support_areas()
|
void TreeSupport::generate_support_areas()
|
||||||
{
|
{
|
||||||
const PrintObjectConfig &config = m_object->config();
|
bool tree_support_enable = m_object_config->enable_support.value && is_tree(m_object_config->support_type.value);
|
||||||
bool tree_support_enable = config.enable_support.value && is_tree(config.support_type.value);
|
|
||||||
if (!tree_support_enable)
|
if (!tree_support_enable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -2007,7 +2009,6 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no
|
||||||
const PrintObjectConfig &config = m_object->config();
|
const PrintObjectConfig &config = m_object->config();
|
||||||
const Print* print = m_object->print();
|
const Print* print = m_object->print();
|
||||||
bool has_brim = print->has_brim();
|
bool has_brim = print->has_brim();
|
||||||
bool has_infill = config.support_base_pattern.value != smpNone && config.support_base_pattern != smpDefault;
|
|
||||||
int bottom_gap_layers = round(m_slicing_params.gap_object_support / m_slicing_params.layer_height);
|
int bottom_gap_layers = round(m_slicing_params.gap_object_support / m_slicing_params.layer_height);
|
||||||
const coordf_t branch_radius = config.tree_support_branch_diameter.value / 2;
|
const coordf_t branch_radius = config.tree_support_branch_diameter.value / 2;
|
||||||
const coordf_t branch_radius_scaled = scale_(branch_radius);
|
const coordf_t branch_radius_scaled = scale_(branch_radius);
|
||||||
|
@ -2328,7 +2329,7 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no
|
||||||
generator = std::make_unique<FillLightning::Generator>(m_object, contours, overhangs, []() {}, support_density);
|
generator = std::make_unique<FillLightning::Generator>(m_object, contours, overhangs, []() {}, support_density);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (!has_infill) {
|
else if (!with_infill) {
|
||||||
// move the holes to contour so they can be well supported
|
// move the holes to contour so they can be well supported
|
||||||
|
|
||||||
// check if poly's contour intersects with expoly's contour
|
// check if poly's contour intersects with expoly's contour
|
||||||
|
@ -2634,16 +2635,7 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
|
||||||
nodes_per_part[0][node.position] = p_node;
|
nodes_per_part[0][node.position] = p_node;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (node.type == ePolygon) {
|
|
||||||
// polygon node do not merge or move
|
|
||||||
const bool to_buildplate = !is_inside_ex(m_ts_data->m_layer_outlines[layer_nr], p_node->position);
|
|
||||||
Node *next_node = new Node(p_node->position, p_node->distance_to_top + 1, p_node->skin_direction, p_node->support_roof_layers_below - 1, to_buildplate, p_node,
|
|
||||||
print_z_next, height_next);
|
|
||||||
next_node->max_move_dist = 0;
|
|
||||||
next_node->is_merged = false;
|
|
||||||
contact_nodes[layer_nr_next].emplace_back(next_node);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* Find which part this node is located in and group the nodes in
|
/* Find which part this node is located in and group the nodes in
|
||||||
* the same part together. Since nodes have a radius and the
|
* the same part together. Since nodes have a radius and the
|
||||||
* avoidance areas are offset by that radius, the set of parts may
|
* avoidance areas are offset by that radius, the set of parts may
|
||||||
|
@ -2711,7 +2703,29 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
|
||||||
continue; //Delete this node (don't create a new node for it on the next layer).
|
continue; //Delete this node (don't create a new node for it on the next layer).
|
||||||
}
|
}
|
||||||
const std::vector<Point>& neighbours = mst.adjacent_nodes(node.position);
|
const std::vector<Point>& neighbours = mst.adjacent_nodes(node.position);
|
||||||
if (neighbours.size() == 1 && vsize2_with_unscale(neighbours[0] - node.position) < max_move_distance2 && mst.adjacent_nodes(neighbours[0]).size() == 1) //We have just two nodes left, and they're very close!
|
if (node.type == ePolygon) {
|
||||||
|
#if 1
|
||||||
|
// Remove all neighbours that are completely inside the polygon and merge them into this node.
|
||||||
|
for (const Point &neighbour : neighbours) {
|
||||||
|
Node * neighbour_node = nodes_per_part[group_index][neighbour];
|
||||||
|
coord_t neighbour_radius = scale_(calc_branch_radius(branch_radius, neighbour_node->dist_mm_to_top, diameter_angle_scale_factor));
|
||||||
|
Point pt_north = neighbour + Point(0, neighbour_radius), pt_south = neighbour - Point(0, neighbour_radius),
|
||||||
|
pt_west = neighbour - Point(neighbour_radius, 0), pt_east = neighbour + Point(neighbour_radius, 0);
|
||||||
|
if (is_inside_ex(*node.overhang, neighbour) && is_inside_ex(*node.overhang, pt_north) && is_inside_ex(*node.overhang, pt_south)
|
||||||
|
&& is_inside_ex(*node.overhang, pt_west) && is_inside_ex(*node.overhang, pt_east)){
|
||||||
|
node.distance_to_top = std::max(node.distance_to_top, neighbour_node->distance_to_top);
|
||||||
|
node.support_roof_layers_below = std::max(node.support_roof_layers_below, neighbour_node->support_roof_layers_below);
|
||||||
|
node.dist_mm_to_top = std::max(node.dist_mm_to_top, neighbour_node->dist_mm_to_top);
|
||||||
|
node.merged_neighbours.push_front(neighbour_node);
|
||||||
|
node.merged_neighbours.insert(node.merged_neighbours.end(), neighbour_node->merged_neighbours.begin(), neighbour_node->merged_neighbours.end());
|
||||||
|
node.is_merged = true;
|
||||||
|
to_delete.insert(neighbour_node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (neighbours.size() == 1 && vsize2_with_unscale(neighbours[0] - node.position) < max_move_distance2 && mst.adjacent_nodes(neighbours[0]).size() == 1 &&
|
||||||
|
nodes_per_part[group_index][neighbours[0]]->type!=ePolygon) // We have just two nodes left, and they're very close, and the only neighbor is not ePolygon
|
||||||
{
|
{
|
||||||
//Insert a completely new node and let both original nodes fade.
|
//Insert a completely new node and let both original nodes fade.
|
||||||
Point next_position = (node.position + neighbours[0]) / 2; //Average position of the two nodes.
|
Point next_position = (node.position + neighbours[0]) / 2; //Average position of the two nodes.
|
||||||
|
@ -2739,7 +2753,7 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
|
||||||
parent = neighbour->parent;
|
parent = neighbour->parent;
|
||||||
|
|
||||||
const bool to_buildplate = !is_inside_ex(m_ts_data->get_avoidance(0, layer_nr_next), next_position);
|
const bool to_buildplate = !is_inside_ex(m_ts_data->get_avoidance(0, layer_nr_next), next_position);
|
||||||
Node * next_node = new Node(next_position, new_distance_to_top, node.skin_direction, new_support_roof_layers_below, to_buildplate, parent,
|
Node * next_node = new Node(next_position, new_distance_to_top, node.skin_direction, new_support_roof_layers_below, to_buildplate, p_node,
|
||||||
layer_heights[layer_nr_next].first, layer_heights[layer_nr_next].second, new_dist_mm_to_top);
|
layer_heights[layer_nr_next].first, layer_heights[layer_nr_next].second, new_dist_mm_to_top);
|
||||||
next_node->movement = next_position - node.position;
|
next_node->movement = next_position - node.position;
|
||||||
get_max_move_dist(next_node);
|
get_max_move_dist(next_node);
|
||||||
|
@ -2759,6 +2773,8 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
|
||||||
if (vsize2_with_unscale(neighbour - node.position) < /*max_move_distance2*/get_max_move_dist(&node,2))
|
if (vsize2_with_unscale(neighbour - node.position) < /*max_move_distance2*/get_max_move_dist(&node,2))
|
||||||
{
|
{
|
||||||
Node* neighbour_node = nodes_per_part[group_index][neighbour];
|
Node* neighbour_node = nodes_per_part[group_index][neighbour];
|
||||||
|
if (neighbour_node->type == ePolygon) continue;
|
||||||
|
|
||||||
node.distance_to_top = std::max(node.distance_to_top, neighbour_node->distance_to_top);
|
node.distance_to_top = std::max(node.distance_to_top, neighbour_node->distance_to_top);
|
||||||
node.support_roof_layers_below = std::max(node.support_roof_layers_below, neighbour_node->support_roof_layers_below);
|
node.support_roof_layers_below = std::max(node.support_roof_layers_below, neighbour_node->support_roof_layers_below);
|
||||||
node.dist_mm_to_top = std::max(node.dist_mm_to_top, neighbour_node->dist_mm_to_top);
|
node.dist_mm_to_top = std::max(node.dist_mm_to_top, neighbour_node->dist_mm_to_top);
|
||||||
|
@ -2780,6 +2796,17 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (node.type == ePolygon) {
|
||||||
|
// polygon node do not merge or move
|
||||||
|
const bool to_buildplate = !is_inside_ex(m_ts_data->m_layer_outlines[layer_nr], p_node->position);
|
||||||
|
Node * next_node = new Node(p_node->position, p_node->distance_to_top + 1, p_node->skin_direction, p_node->support_roof_layers_below - 1, to_buildplate,
|
||||||
|
p_node, print_z_next, height_next);
|
||||||
|
next_node->max_move_dist = 0;
|
||||||
|
next_node->is_merged = false;
|
||||||
|
contact_nodes[layer_nr_next].emplace_back(next_node);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
//If the branch falls completely inside a collision area (the entire branch would be removed by the X/Y offset), delete it.
|
//If the branch falls completely inside a collision area (the entire branch would be removed by the X/Y offset), delete it.
|
||||||
if (group_index > 0 && is_inside_ex(m_ts_data->get_collision(m_ts_data->m_xy_distance, layer_nr), node.position))
|
if (group_index > 0 && is_inside_ex(m_ts_data->get_collision(m_ts_data->m_xy_distance, layer_nr), node.position))
|
||||||
{
|
{
|
||||||
|
@ -2926,10 +2953,12 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
||||||
draw_contours_and_nodes_to_svg(std::to_string(ts_layer->print_z), m_ts_data->get_avoidance(0, layer_nr), m_ts_data->get_avoidance(branch_radius_temp, layer_nr), m_ts_data->m_layer_outlines_below[layer_nr],
|
if (contact_nodes[layer_nr].empty() == false) {
|
||||||
|
draw_contours_and_nodes_to_svg((boost::format("%.2f") % contact_nodes[layer_nr][0]->print_z).str(), m_ts_data->get_avoidance(0, layer_nr),
|
||||||
|
m_ts_data->get_avoidance(branch_radius_temp, layer_nr),
|
||||||
|
m_ts_data->m_layer_outlines_below[layer_nr],
|
||||||
contact_nodes[layer_nr], contact_nodes[layer_nr_next], "contact_points", { "overhang","avoid","outline" }, { "blue","red","yellow" });
|
contact_nodes[layer_nr], contact_nodes[layer_nr_next], "contact_points", { "overhang","avoid","outline" }, { "blue","red","yellow" });
|
||||||
|
|
||||||
if (contact_nodes[layer_nr].empty() == false) {
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "drop_nodes layer " << layer_nr << ", print_z=" << ts_layer->print_z;
|
BOOST_LOG_TRIVIAL(debug) << "drop_nodes layer " << layer_nr << ", print_z=" << ts_layer->print_z;
|
||||||
for (size_t i = 0; i < std::min(size_t(5), contact_nodes[layer_nr].size()); i++) {
|
for (size_t i = 0; i < std::min(size_t(5), contact_nodes[layer_nr].size()); i++) {
|
||||||
auto &node = contact_nodes[layer_nr][i];
|
auto &node = contact_nodes[layer_nr][i];
|
||||||
|
@ -2960,7 +2989,7 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
// delete nodes with no children (means either it's a single layer nodes, or the branch has been deleted but not completely)
|
// delete nodes with no children (means either it's a single layer nodes, or the branch has been deleted but not completely)
|
||||||
for (size_t layer_nr = contact_nodes.size() - 1; layer_nr > 0; layer_nr--){
|
for (size_t layer_nr = contact_nodes.size() - 1; layer_nr > 0; layer_nr--){
|
||||||
auto layer_contact_nodes = contact_nodes[layer_nr];
|
auto layer_contact_nodes = contact_nodes[layer_nr];
|
||||||
|
@ -2974,7 +3003,7 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
BOOST_LOG_TRIVIAL(debug) << "after m_avoidance_cache.size()=" << m_ts_data->m_avoidance_cache.size();
|
BOOST_LOG_TRIVIAL(debug) << "after m_avoidance_cache.size()=" << m_ts_data->m_avoidance_cache.size();
|
||||||
|
|
||||||
for (Node *node : to_free_node_set)
|
for (Node *node : to_free_node_set)
|
||||||
|
@ -3242,16 +3271,6 @@ std::vector<std::pair<coordf_t, coordf_t>> TreeSupport::plan_layer_heights(std::
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
||||||
// export all print_z and layer height into .txt
|
|
||||||
std::ofstream layer_heights_out;
|
|
||||||
layer_heights_out.open("./SVG/layer_heights_out.txt");
|
|
||||||
//layer_heights_out.open("layer_heights_out.txt");
|
|
||||||
if (layer_heights_out.is_open()) {
|
|
||||||
for (int i = 0; i < layer_heights.size(); i++) {
|
|
||||||
layer_heights_out << layer_heights[i].first << " " << layer_heights[i].second << std::endl;
|
|
||||||
}
|
|
||||||
layer_heights_out.close();
|
|
||||||
}
|
|
||||||
// check bounds
|
// check bounds
|
||||||
if (1)
|
if (1)
|
||||||
{
|
{
|
||||||
|
@ -3264,6 +3283,7 @@ std::vector<std::pair<coordf_t, coordf_t>> TreeSupport::plan_layer_heights(std::
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
for (int i = 0; i < layer_heights.size(); i++) { BOOST_LOG_TRIVIAL(info) << "plan_layer_heights print_z, height: "<< layer_heights[i].first << " " << layer_heights[i].second << std::endl; }
|
||||||
|
|
||||||
return layer_heights;
|
return layer_heights;
|
||||||
}
|
}
|
||||||
|
@ -3549,7 +3569,7 @@ Polygons TreeSupportData::get_contours_with_holes(size_t layer_nr) const
|
||||||
|
|
||||||
coordf_t TreeSupportData::ceil_radius(coordf_t radius) const
|
coordf_t TreeSupportData::ceil_radius(coordf_t radius) const
|
||||||
{
|
{
|
||||||
#if 0
|
#if 1
|
||||||
size_t factor = (size_t)(radius / m_radius_sample_resolution);
|
size_t factor = (size_t)(radius / m_radius_sample_resolution);
|
||||||
coordf_t remains = radius - m_radius_sample_resolution * factor;
|
coordf_t remains = radius - m_radius_sample_resolution * factor;
|
||||||
if (remains > EPSILON) {
|
if (remains > EPSILON) {
|
||||||
|
@ -3604,7 +3624,7 @@ const ExPolygons& TreeSupportData::calculate_avoidance(const RadiusLayerPair& ke
|
||||||
avoidance_areas.insert(avoidance_areas.end(), collision.begin(), collision.end());
|
avoidance_areas.insert(avoidance_areas.end(), collision.begin(), collision.end());
|
||||||
avoidance_areas = std::move(union_ex(avoidance_areas));
|
avoidance_areas = std::move(union_ex(avoidance_areas));
|
||||||
ret = m_avoidance_cache.insert({key, std::move(avoidance_areas)});
|
ret = m_avoidance_cache.insert({key, std::move(avoidance_areas)});
|
||||||
assert(ret.second);
|
//assert(ret.second);
|
||||||
} else {
|
} else {
|
||||||
ExPolygons avoidance_areas = std::move(offset_ex(m_layer_outlines_below[layer_nr], scale_(m_xy_distance + radius)));
|
ExPolygons avoidance_areas = std::move(offset_ex(m_layer_outlines_below[layer_nr], scale_(m_xy_distance + radius)));
|
||||||
ret = m_avoidance_cache.insert({key, std::move(avoidance_areas)});
|
ret = m_avoidance_cache.insert({key, std::move(avoidance_areas)});
|
||||||
|
|
|
@ -384,6 +384,7 @@ private:
|
||||||
coordf_t MIN_BRANCH_RADIUS = 0.5;
|
coordf_t MIN_BRANCH_RADIUS = 0.5;
|
||||||
float tree_support_branch_diameter_angle = 5.0;
|
float tree_support_branch_diameter_angle = 5.0;
|
||||||
bool is_slim = false;
|
bool is_slim = false;
|
||||||
|
bool with_infill = false;
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -1434,6 +1434,22 @@ 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);
|
||||||
}
|
}
|
||||||
wxGetApp().plater()->update();
|
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 recommand the following settings: at least 2 interface layers, at least 0.1 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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue