ENH: use print volume to clip tree support

So tree supports won't go outside the bed.

Known issue:
1. moving won't trigger support re-calculating, so if you want to
  clip the supports in a different way after moving, you need to change
  the support settings (eg change threshold angle to 31 degrees).
2. clipping with the occlusion region is not complete, and an error
  message of "outside toolpath" will still be popped because we use
  convex hull to detection confliction.

Jira: STUDIO-2036

Change-Id: I643b14618eb18ffa9825072c44f677e51b0ff937
(cherry picked from commit a6217824dc0f490027e16f80f810d176dec6004b)
This commit is contained in:
Arthur Tang 2022-12-15 13:03:53 +08:00 committed by Lane.Wei
parent b144aae5bd
commit c07dcffe16
4 changed files with 38 additions and 17 deletions

View File

@ -4793,6 +4793,26 @@ Points get_bed_shape(const PrintConfig &cfg)
Points get_bed_shape(const SLAPrinterConfig &cfg) { return to_points(cfg.printable_area.values); } Points get_bed_shape(const SLAPrinterConfig &cfg) { return to_points(cfg.printable_area.values); }
Polygon get_bed_shape_with_excluded_area(const PrintConfig& cfg)
{
Polygon bed_poly;
bed_poly.points = get_bed_shape(cfg);
Points excluse_area_points = to_points(cfg.bed_exclude_area.values);
Polygons exclude_polys;
Polygon exclude_poly;
for (int i = 0; i < excluse_area_points.size(); i++) {
auto pt = excluse_area_points[i];
exclude_poly.points.emplace_back(pt);
if (i % 4 == 3) { // exclude areas are always rectangle
exclude_polys.push_back(exclude_poly);
exclude_poly.points.clear();
}
}
auto tmp = diff({ bed_poly }, exclude_polys);
if (!tmp.empty()) bed_poly = tmp[0];
return bed_poly;
}
} // namespace Slic3r } // namespace Slic3r
#include <cereal/types/polymorphic.hpp> #include <cereal/types/polymorphic.hpp>

View File

@ -18,7 +18,7 @@
#include "libslic3r.h" #include "libslic3r.h"
#include "Config.hpp" #include "Config.hpp"
#include "Polygon.hpp"
#include <boost/preprocessor/facilities/empty.hpp> #include <boost/preprocessor/facilities/empty.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp> #include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/preprocessor/seq/for_each.hpp> #include <boost/preprocessor/seq/for_each.hpp>
@ -1241,6 +1241,7 @@ private:
Points get_bed_shape(const DynamicPrintConfig &cfg); Points get_bed_shape(const DynamicPrintConfig &cfg);
Points get_bed_shape(const PrintConfig &cfg); Points get_bed_shape(const PrintConfig &cfg);
Points get_bed_shape(const SLAPrinterConfig &cfg); Points get_bed_shape(const SLAPrinterConfig &cfg);
Slic3r::Polygon get_bed_shape_with_excluded_area(const PrintConfig& cfg);
// ModelConfig is a wrapper around DynamicPrintConfig with an addition of a timestamp. // ModelConfig is a wrapper around DynamicPrintConfig with an addition of a timestamp.
// Each change of ModelConfig is tracked by assigning a new timestamp from a global counter. // Each change of ModelConfig is tracked by assigning a new timestamp from a global counter.

View File

@ -704,6 +704,13 @@ TreeSupport::TreeSupport(PrintObject& object, const SlicingParameters &slicing_p
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. // by default tree support needs no infill, unless it's tree hybrid which contains normal nodes.
with_infill = support_pattern != smpNone && support_pattern != smpDefault; with_infill = support_pattern != smpNone && support_pattern != smpDefault;
const PrintConfig& print_config = m_object->print()->config();
m_machine_border.contour = get_bed_shape_with_excluded_area(print_config);
m_machine_border.translate(-m_object->instances().front().shift); // align with the centered object
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
SVG svg("SVG/machine_boarder.svg", m_object->bounding_box());
if (svg.is_opened()) svg.draw(m_machine_border, "yellow");
#endif
} }
@ -2210,18 +2217,20 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no
//roof_areas = std::move(diff_ex(roof_areas, avoid_region_interface)); //roof_areas = std::move(diff_ex(roof_areas, avoid_region_interface));
//roof_1st_layer = std::move(diff_ex(roof_1st_layer, avoid_region_interface)); //roof_1st_layer = std::move(diff_ex(roof_1st_layer, avoid_region_interface));
roof_areas = avoid_object_remove_extra_small_parts(roof_areas, avoid_region_interface); roof_areas = avoid_object_remove_extra_small_parts(roof_areas, avoid_region_interface);
roof_areas = intersection_ex(roof_areas, m_machine_border);
roof_1st_layer = avoid_object_remove_extra_small_parts(roof_1st_layer, avoid_region_interface); roof_1st_layer = avoid_object_remove_extra_small_parts(roof_1st_layer, avoid_region_interface);
// roof_1st_layer and roof_areas may intersect, so need to subtract roof_areas from roof_1st_layer // roof_1st_layer and roof_areas may intersect, so need to subtract roof_areas from roof_1st_layer
roof_1st_layer = std::move(diff_ex(roof_1st_layer, roof_areas)); roof_1st_layer = std::move(diff_ex(roof_1st_layer, roof_areas));
roof_1st_layer = intersection_ex(roof_1st_layer, m_machine_border);
// let supports touch objects when brim is on // let supports touch objects when brim is on
auto avoid_region = m_ts_data->get_collision((layer_nr == 0 && has_brim) ? config.brim_object_gap : m_ts_data->m_xy_distance, layer_nr); auto avoid_region = m_ts_data->get_collision((layer_nr == 0 && has_brim) ? config.brim_object_gap : m_ts_data->m_xy_distance, layer_nr);
// base_areas = std::move(diff_ex(base_areas, avoid_region));
base_areas = avoid_object_remove_extra_small_parts(base_areas, avoid_region); base_areas = avoid_object_remove_extra_small_parts(base_areas, avoid_region);
base_areas = std::move(diff_ex(base_areas, roof_areas)); base_areas = std::move(diff_ex(base_areas, roof_areas));
base_areas = std::move(diff_ex(base_areas, roof_1st_layer)); base_areas = std::move(diff_ex(base_areas, roof_1st_layer));
base_areas = std::move(diff_ex(base_areas, roof_gap_areas)); base_areas = std::move(diff_ex(base_areas, roof_gap_areas));
base_areas = intersection_ex(base_areas, m_machine_border);
if (SQUARE_SUPPORT) { if (SQUARE_SUPPORT) {
// simplify support contours // simplify support contours
@ -3504,16 +3513,6 @@ void TreeSupport::generate_contact_points(std::vector<std::vector<TreeSupport::N
BOOST_LOG_TRIVIAL(info) << "avg_node_per_layer=" << avg_node_per_layer << ", nodes_angle=" << nodes_angle; BOOST_LOG_TRIVIAL(info) << "avg_node_per_layer=" << avg_node_per_layer << ", nodes_angle=" << nodes_angle;
} }
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
std::ofstream contact_nodes_out;
contact_nodes_out.open("./SVG/contact_nodes.txt");
if (contact_nodes_out.is_open()) {
for (int i = 0; i < contact_nodes.size(); i++) {
if (!contact_nodes[i].empty())
contact_nodes_out << i << std::endl;
}
}
#endif // SUPPORT_TREE_DEBUG_TO_SVG
} }
void TreeSupport::insert_dropped_node(std::vector<Node*>& nodes_layer, Node* p_node) void TreeSupport::insert_dropped_node(std::vector<Node*>& nodes_layer, Node* p_node)

View File

@ -125,11 +125,6 @@ private:
*/ */
const ExPolygons& calculate_avoidance(const RadiusLayerPair& key) const; const ExPolygons& calculate_avoidance(const RadiusLayerPair& key) const;
/*!
* \brief Polygons representing the limits of the printable area of the
* machine
*/
ExPolygon m_machine_border;
public: public:
bool is_slim = false; bool is_slim = false;
@ -401,6 +396,12 @@ private:
bool with_infill = false; bool with_infill = false;
/*!
* \brief Polygons representing the limits of the printable area of the
* machine
*/
ExPolygon m_machine_border;
/*! /*!
* \brief Draws circles around each node of the tree into the final support. * \brief Draws circles around each node of the tree into the final support.
* *