ENH: fixed crash issue of lightning infill of tree support
Use clipper2 and remove colinear points. Later on we can try to set lightning infill as the default infill pattern of tree support. jira: none Change-Id: Id545b15d778071cec6e56d212ab68db1ab90ad2a
This commit is contained in:
parent
26881072a4
commit
2debc31c4d
|
@ -79,6 +79,14 @@ static ExPolygons PolyTreeToExPolygons(Clipper2Lib::PolyTree64 &&polytree)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SimplifyPolyTree(const Clipper2Lib::PolyPath64 &polytree, double epsilon, Clipper2Lib::PolyPath64 &result)
|
||||||
|
{
|
||||||
|
for (const auto &child : polytree) {
|
||||||
|
Clipper2Lib::PolyPath64 *newchild = result.AddChild(Clipper2Lib::SimplifyPath(child->Polygon(), epsilon));
|
||||||
|
SimplifyPolyTree(*child, epsilon, *newchild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Clipper2Lib::Paths64 Slic3rPolygons_to_Paths64(const Polygons &in)
|
Clipper2Lib::Paths64 Slic3rPolygons_to_Paths64(const Polygons &in)
|
||||||
{
|
{
|
||||||
Clipper2Lib::Paths64 out;
|
Clipper2Lib::Paths64 out;
|
||||||
|
@ -132,7 +140,7 @@ Slic3r::Polylines intersection_pl_2(const Slic3r::Polylines& subject, const Slic
|
||||||
Slic3r::Polylines diff_pl_2(const Slic3r::Polylines& subject, const Slic3r::Polygons& clip)
|
Slic3r::Polylines diff_pl_2(const Slic3r::Polylines& subject, const Slic3r::Polygons& clip)
|
||||||
{ return _clipper2_pl_open(Clipper2Lib::ClipType::Difference, subject, clip); }
|
{ return _clipper2_pl_open(Clipper2Lib::ClipType::Difference, subject, clip); }
|
||||||
|
|
||||||
ExPolygons union_ex2(const Polygons& polygons)
|
ExPolygons union_ex_2(const Polygons& polygons)
|
||||||
{
|
{
|
||||||
Clipper2Lib::Clipper64 c;
|
Clipper2Lib::Clipper64 c;
|
||||||
c.AddSubject(Slic3rPolygons_to_Paths64(polygons));
|
c.AddSubject(Slic3rPolygons_to_Paths64(polygons));
|
||||||
|
@ -147,7 +155,7 @@ ExPolygons union_ex2(const Polygons& polygons)
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExPolygons union_ex2(const ExPolygons &expolygons)
|
ExPolygons union_ex_2(const ExPolygons &expolygons)
|
||||||
{
|
{
|
||||||
Clipper2Lib::Clipper64 c;
|
Clipper2Lib::Clipper64 c;
|
||||||
c.AddSubject(Slic3rExPolygons_to_Paths64(expolygons));
|
c.AddSubject(Slic3rExPolygons_to_Paths64(expolygons));
|
||||||
|
@ -161,4 +169,43 @@ ExPolygons union_ex2(const ExPolygons &expolygons)
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// 对 ExPolygons 进行偏移
|
||||||
|
ExPolygons offset_ex_2(const ExPolygons &expolygons, double delta)
|
||||||
|
{
|
||||||
|
Clipper2Lib::Paths64 subject = Slic3rExPolygons_to_Paths64(expolygons);
|
||||||
|
Clipper2Lib::ClipperOffset offsetter;
|
||||||
|
offsetter.AddPaths(subject, Clipper2Lib::JoinType::Round, Clipper2Lib::EndType::Polygon);
|
||||||
|
Clipper2Lib::PolyPath64 polytree;
|
||||||
|
offsetter.Execute(delta, polytree);
|
||||||
|
ExPolygons results = PolyTreeToExPolygons(std::move(polytree));
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExPolygons offset2_ex_2(const ExPolygons& expolygons, double delta1, double delta2)
|
||||||
|
{
|
||||||
|
// 1st offset
|
||||||
|
Clipper2Lib::Paths64 subject = Slic3rExPolygons_to_Paths64(expolygons);
|
||||||
|
Clipper2Lib::ClipperOffset offsetter;
|
||||||
|
offsetter.AddPaths(subject, Clipper2Lib::JoinType::Round, Clipper2Lib::EndType::Polygon);
|
||||||
|
Clipper2Lib::PolyPath64 polytree;
|
||||||
|
offsetter.Execute(delta1, polytree);
|
||||||
|
|
||||||
|
// simplify the result
|
||||||
|
Clipper2Lib::PolyPath64 polytree2;
|
||||||
|
SimplifyPolyTree(polytree, SCALED_EPSILON, polytree2);
|
||||||
|
|
||||||
|
// 2nd offset
|
||||||
|
offsetter.Clear();
|
||||||
|
offsetter.AddPaths(Clipper2Lib::PolyTreeToPaths64(polytree2), Clipper2Lib::JoinType::Round, Clipper2Lib::EndType::Polygon);
|
||||||
|
polytree.Clear();
|
||||||
|
offsetter.Execute(delta2, polytree);
|
||||||
|
|
||||||
|
// convert back to expolygons
|
||||||
|
ExPolygons results = PolyTreeToExPolygons(std::move(polytree));
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Slic3r
|
|
@ -8,8 +8,10 @@ namespace Slic3r {
|
||||||
|
|
||||||
Slic3r::Polylines intersection_pl_2(const Slic3r::Polylines& subject, const Slic3r::Polygons& clip);
|
Slic3r::Polylines intersection_pl_2(const Slic3r::Polylines& subject, const Slic3r::Polygons& clip);
|
||||||
Slic3r::Polylines diff_pl_2(const Slic3r::Polylines& subject, const Slic3r::Polygons& clip);
|
Slic3r::Polylines diff_pl_2(const Slic3r::Polylines& subject, const Slic3r::Polygons& clip);
|
||||||
ExPolygons union_ex2(const Polygons &expolygons);
|
ExPolygons union_ex_2(const Polygons &expolygons);
|
||||||
ExPolygons union_ex2(const ExPolygons &expolygons);
|
ExPolygons union_ex_2(const ExPolygons &expolygons);
|
||||||
|
ExPolygons offset_ex_2(const ExPolygons &expolygons, double delta);
|
||||||
|
ExPolygons offset2_ex_2(const ExPolygons &expolygons, double delta1, double delta2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -413,6 +413,18 @@ Lines ExPolygon::lines() const
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ExPolygon::remove_colinear_points() {
|
||||||
|
bool removed = this->contour.remove_colinear_points();
|
||||||
|
if (contour.size() < 3) {
|
||||||
|
contour.points.clear();
|
||||||
|
holes.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (Polygon &hole : this->holes)
|
||||||
|
removed |= hole.remove_colinear_points();
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
|
|
||||||
// Do expolygons match? If they match, they must have the same topology,
|
// Do expolygons match? If they match, they must have the same topology,
|
||||||
// however their contours may be rotated.
|
// however their contours may be rotated.
|
||||||
bool expolygons_match(const ExPolygon &l, const ExPolygon &r)
|
bool expolygons_match(const ExPolygon &l, const ExPolygon &r)
|
||||||
|
|
|
@ -76,6 +76,8 @@ public:
|
||||||
{ Polylines out; this->medial_axis(min_width, max_width, &out); return out; }
|
{ Polylines out; this->medial_axis(min_width, max_width, &out); return out; }
|
||||||
Lines lines() const;
|
Lines lines() const;
|
||||||
|
|
||||||
|
bool remove_colinear_points();
|
||||||
|
|
||||||
// Number of contours (outer contour with holes).
|
// Number of contours (outer contour with holes).
|
||||||
size_t num_contours() const { return this->holes.size() + 1; }
|
size_t num_contours() const { return this->holes.size() + 1; }
|
||||||
Polygon& contour_or_hole(size_t idx) { return (idx == 0) ? this->contour : this->holes[idx - 1]; }
|
Polygon& contour_or_hole(size_t idx) { return (idx == 0) ? this->contour : this->holes[idx - 1]; }
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "DistanceField.hpp" //Class we're implementing.
|
#include "DistanceField.hpp" //Class we're implementing.
|
||||||
#include "../FillRectilinear.hpp"
|
#include "../FillRectilinear.hpp"
|
||||||
#include "../../ClipperUtils.hpp"
|
#include "../../ClipperUtils.hpp"
|
||||||
|
#include "../../Clipper2Utils.hpp"
|
||||||
|
|
||||||
#include <tbb/parallel_for.h>
|
#include <tbb/parallel_for.h>
|
||||||
|
|
||||||
|
@ -43,7 +44,8 @@ DistanceField::DistanceField(const coord_t& radius, const Polygons& current_outl
|
||||||
m_supporting_radius2 = Slic3r::sqr(int64_t(radius));
|
m_supporting_radius2 = Slic3r::sqr(int64_t(radius));
|
||||||
// Sample source polygons with a regular grid sampling pattern.
|
// Sample source polygons with a regular grid sampling pattern.
|
||||||
const BoundingBox overhang_bbox = get_extents(current_overhang);
|
const BoundingBox overhang_bbox = get_extents(current_overhang);
|
||||||
ExPolygons expolys = offset2_ex(union_ex(current_overhang), -m_cell_size / 2, m_cell_size / 2); // remove dangling lines which causes sample_grid_pattern crash (fails the OUTER_LOW assertions)
|
// remove dangling lines which causes sample_grid_pattern crash (fails the OUTER_LOW assertions)
|
||||||
|
ExPolygons expolys = offset2_ex_2(union_ex_2(current_overhang), -m_cell_size / 2, m_cell_size / 2);
|
||||||
for (const ExPolygon &expoly : expolys) {
|
for (const ExPolygon &expoly : expolys) {
|
||||||
const Points sampled_points = sample_grid_pattern(expoly, m_cell_size, overhang_bbox);
|
const Points sampled_points = sample_grid_pattern(expoly, m_cell_size, overhang_bbox);
|
||||||
const size_t unsupported_points_prev_size = m_unsupported_points.size();
|
const size_t unsupported_points_prev_size = m_unsupported_points.size();
|
||||||
|
|
|
@ -118,6 +118,21 @@ bool MultiPoint::remove_duplicate_points()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MultiPoint::remove_colinear_points() {
|
||||||
|
if (points.size() < 3) return false;
|
||||||
|
bool changed = false;
|
||||||
|
for (size_t i = 1; i < points.size() - 1; ) {
|
||||||
|
if (Line::distance_to_infinite_squared(points[i], points[i - 1], points[i+1]) < SCALED_EPSILON) {
|
||||||
|
points.erase(points.begin() + i);
|
||||||
|
changed = true;
|
||||||
|
} else {
|
||||||
|
++ i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (points.size() < 3) points.clear();
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
bool MultiPoint::intersection(const Line& line, Point* intersection) const
|
bool MultiPoint::intersection(const Line& line, Point* intersection) const
|
||||||
{
|
{
|
||||||
Lines lines = this->lines();
|
Lines lines = this->lines();
|
||||||
|
|
|
@ -77,6 +77,7 @@ public:
|
||||||
bool has_duplicate_points() const;
|
bool has_duplicate_points() const;
|
||||||
// Remove exact duplicates, return true if any duplicate has been removed.
|
// Remove exact duplicates, return true if any duplicate has been removed.
|
||||||
bool remove_duplicate_points();
|
bool remove_duplicate_points();
|
||||||
|
bool remove_colinear_points();
|
||||||
void clear() { this->points.clear(); }
|
void clear() { this->points.clear(); }
|
||||||
void append(const Point &point) { this->points.push_back(point); }
|
void append(const Point &point) { this->points.push_back(point); }
|
||||||
void append(const Points &src) { this->append(src.begin(), src.end()); }
|
void append(const Points &src) { this->append(src.begin(), src.end()); }
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "format.hpp"
|
#include "format.hpp"
|
||||||
|
#include "BuildVolume.hpp"
|
||||||
#include "ClipperUtils.hpp"
|
#include "ClipperUtils.hpp"
|
||||||
#include "Clipper2Utils.hpp"
|
#include "Clipper2Utils.hpp"
|
||||||
#include "Fill/FillBase.hpp"
|
#include "Fill/FillBase.hpp"
|
||||||
|
@ -25,6 +26,13 @@
|
||||||
#include <tbb/parallel_for_each.h>
|
#include <tbb/parallel_for_each.h>
|
||||||
|
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
|
// #include <boost/log/core.hpp>
|
||||||
|
// #include <boost/log/expressions.hpp>
|
||||||
|
// #include <boost/log/sources/severity_logger.hpp>
|
||||||
|
// #include <boost/log/sources/record_ostream.hpp>
|
||||||
|
// #include <boost/log/utility/setup/file.hpp>
|
||||||
|
// #include <boost/log/utility/setup/common_attributes.hpp>
|
||||||
|
// #include <boost/log/utility/setup/console.hpp>
|
||||||
|
|
||||||
#ifndef M_PI
|
#ifndef M_PI
|
||||||
#define M_PI 3.1415926535897932384626433832795
|
#define M_PI 3.1415926535897932384626433832795
|
||||||
|
@ -605,7 +613,7 @@ TreeSupport::TreeSupport(PrintObject& object, const SlicingParameters &slicing_p
|
||||||
|
|
||||||
SupportMaterialPattern support_pattern = m_object_config->support_base_pattern;
|
SupportMaterialPattern support_pattern = m_object_config->support_base_pattern;
|
||||||
if (m_support_params.support_style == smsTreeHybrid && support_pattern == smpDefault)
|
if (m_support_params.support_style == smsTreeHybrid && support_pattern == smpDefault)
|
||||||
support_pattern = smpRectilinear;
|
support_pattern = smpRectilinear;//smpLightning;
|
||||||
|
|
||||||
if(support_pattern == smpLightning)
|
if(support_pattern == smpLightning)
|
||||||
m_support_params.base_fill_pattern = ipLightning;
|
m_support_params.base_fill_pattern = ipLightning;
|
||||||
|
@ -622,7 +630,8 @@ TreeSupport::TreeSupport(PrintObject& object, const SlicingParameters &slicing_p
|
||||||
|
|
||||||
m_ts_data = m_object->alloc_tree_support_preview_cache();
|
m_ts_data = m_object->alloc_tree_support_preview_cache();
|
||||||
top_z_distance = m_object_config->support_top_z_distance.value;
|
top_z_distance = m_object_config->support_top_z_distance.value;
|
||||||
if (top_z_distance > EPSILON) top_z_distance = std::max(top_z_distance, float(m_slicing_params.min_layer_height));
|
if (top_z_distance > EPSILON)
|
||||||
|
top_z_distance = std::max(top_z_distance, float(m_slicing_params.min_layer_height));
|
||||||
#if USE_TREESUPPRT3D
|
#if USE_TREESUPPRT3D
|
||||||
m_support_params.independent_layer_height = false; // do not use independent layer height for 3D tree support
|
m_support_params.independent_layer_height = false; // do not use independent layer height for 3D tree support
|
||||||
#endif
|
#endif
|
||||||
|
@ -956,7 +965,7 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/)
|
||||||
auto cluster_boundary_ex = intersection_ex(poly, lower_layer_offseted);
|
auto cluster_boundary_ex = intersection_ex(poly, lower_layer_offseted);
|
||||||
Polygons cluster_boundary = to_polygons(cluster_boundary_ex);
|
Polygons cluster_boundary = to_polygons(cluster_boundary_ex);
|
||||||
if (cluster_boundary.empty()) continue;
|
if (cluster_boundary.empty()) continue;
|
||||||
|
|
||||||
for (auto &pt : poly.contour.points) {
|
for (auto &pt : poly.contour.points) {
|
||||||
double dist_pt = std::numeric_limits<double>::max();
|
double dist_pt = std::numeric_limits<double>::max();
|
||||||
for (auto &ply : cluster_boundary) {
|
for (auto &ply : cluster_boundary) {
|
||||||
|
@ -1589,7 +1598,7 @@ void TreeSupport::generate_toolpaths()
|
||||||
if (area_group.type == SupportLayer::Roof1stLayer) {
|
if (area_group.type == SupportLayer::Roof1stLayer) {
|
||||||
// use higher flow for roof_1st_layer ?
|
// use higher flow for roof_1st_layer ?
|
||||||
Flow roof_1st_layer_flow = support_material_interface_flow(m_object, ts_layer->height)/*.with_flow_ratio(1.5)*/;
|
Flow roof_1st_layer_flow = support_material_interface_flow(m_object, ts_layer->height)/*.with_flow_ratio(1.5)*/;
|
||||||
|
|
||||||
// Note: spacing means the separation between two lines as if they are tightly extruded
|
// Note: spacing means the separation between two lines as if they are tightly extruded
|
||||||
filler_Roof1stLayer->spacing = roof_1st_layer_flow.spacing();
|
filler_Roof1stLayer->spacing = roof_1st_layer_flow.spacing();
|
||||||
// generate a perimeter first to support interface better
|
// generate a perimeter first to support interface better
|
||||||
|
@ -1629,9 +1638,9 @@ void TreeSupport::generate_toolpaths()
|
||||||
if(m_object_config->support_base_pattern==smpDefault)
|
if(m_object_config->support_base_pattern==smpDefault)
|
||||||
need_infill &= area_group.need_infill;
|
need_infill &= area_group.need_infill;
|
||||||
|
|
||||||
std::shared_ptr<Fill> filler_support = std::shared_ptr<Fill>(Fill::new_from_type(layer_id == 0 ? ipConcentric : m_support_params.base_fill_pattern));
|
std::shared_ptr<Fill> filler_support = std::shared_ptr<Fill>(Fill::new_from_type(layer_id == 0 ? ipConcentric : m_support_params.base_fill_pattern));
|
||||||
filler_support->set_bounding_box(bbox_object);
|
filler_support->set_bounding_box(bbox_object);
|
||||||
filler_support->spacing = support_flow.spacing();
|
filler_support->spacing = support_flow.spacing();
|
||||||
filler_support->angle = Geometry::deg2rad(object_config.support_angle.value);
|
filler_support->angle = Geometry::deg2rad(object_config.support_angle.value);
|
||||||
|
|
||||||
Polygons loops = to_polygons(poly);
|
Polygons loops = to_polygons(poly);
|
||||||
|
@ -1786,8 +1795,10 @@ void TreeSupport::generate()
|
||||||
profiler.stage_start(STAGE_GENERATE_CONTACT_NODES);
|
profiler.stage_start(STAGE_GENERATE_CONTACT_NODES);
|
||||||
//m_object->print()->set_status(56, _u8L("Support: precalculate avoidance"));
|
//m_object->print()->set_status(56, _u8L("Support: precalculate avoidance"));
|
||||||
|
|
||||||
Points bedpts = m_machine_border.contour.points;
|
Points bedpts = m_machine_border.contour.points;
|
||||||
BuildVolume build_volume{ Pointfs{ unscaled(bedpts[0]), unscaled(bedpts[1]),unscaled(bedpts[2]),unscaled(bedpts[3])}, m_print_config->printable_height };
|
Pointfs bedptsf;
|
||||||
|
std::transform(bedpts.begin(), bedpts.end(), std::back_inserter(bedptsf), [](const Point &p) { return unscale(p); });
|
||||||
|
BuildVolume build_volume{bedptsf, m_print_config->printable_height, {}};
|
||||||
TreeSupport3D::TreeSupportSettings tree_support_3d_config{ TreeSupport3D::TreeSupportMeshGroupSettings{ *m_object }, m_slicing_params };
|
TreeSupport3D::TreeSupportSettings tree_support_3d_config{ TreeSupport3D::TreeSupportMeshGroupSettings{ *m_object }, m_slicing_params };
|
||||||
m_model_volumes = std::make_unique<TreeSupport3D::TreeModelVolumes>( *m_object, build_volume, tree_support_3d_config.maximum_move_distance, tree_support_3d_config.maximum_move_distance_slow, 1);
|
m_model_volumes = std::make_unique<TreeSupport3D::TreeModelVolumes>( *m_object, build_volume, tree_support_3d_config.maximum_move_distance, tree_support_3d_config.maximum_move_distance_slow, 1);
|
||||||
// ### Precalculate avoidances, collision etc.
|
// ### Precalculate avoidances, collision etc.
|
||||||
|
@ -2101,12 +2112,11 @@ void TreeSupport::draw_circles()
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate areas
|
// generate areas
|
||||||
const coordf_t layer_height = config.layer_height.value;
|
|
||||||
const size_t top_interface_layers = config.support_interface_top_layers.value;
|
const size_t top_interface_layers = config.support_interface_top_layers.value;
|
||||||
const size_t bottom_interface_layers = config.support_interface_bottom_layers.value;
|
const size_t bottom_interface_layers = config.support_interface_bottom_layers.value;
|
||||||
const bool with_lightning_infill = m_support_params.base_fill_pattern == ipLightning;
|
const bool with_lightning_infill = m_support_params.base_fill_pattern == ipLightning;
|
||||||
coordf_t support_extrusion_width = m_support_params.support_extrusion_width;
|
coordf_t support_extrusion_width = m_support_params.support_extrusion_width;
|
||||||
const coordf_t line_width_scaled = scale_(support_extrusion_width);
|
const coordf_t line_width_scaled = scale_(support_extrusion_width);
|
||||||
const float tree_brim_width = config.raft_first_layer_expansion.value;
|
const float tree_brim_width = config.raft_first_layer_expansion.value;
|
||||||
|
|
||||||
if (m_object->support_layer_count() <= m_raft_layers)
|
if (m_object->support_layer_count() <= m_raft_layers)
|
||||||
|
@ -2243,7 +2253,7 @@ void TreeSupport::draw_circles()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layer_nr == 0 && m_raft_layers == 0)
|
if (layer_nr == 0 && m_raft_layers == 0)
|
||||||
area = safe_offset_inc(area, scale_(brim_width), get_collision(false), scale_(MIN_BRANCH_RADIUS * 0.5), 0, 1);
|
area = safe_offset_inc(area, scale_(brim_width), get_collision(false), scale_(MIN_BRANCH_RADIUS * 0.5), 0, 1);
|
||||||
if (obj_layer_nr>0 && node.distance_to_top < 0)
|
if (obj_layer_nr>0 && node.distance_to_top < 0)
|
||||||
append(roof_gap_areas, area);
|
append(roof_gap_areas, area);
|
||||||
|
@ -2365,8 +2375,6 @@ void TreeSupport::draw_circles()
|
||||||
|
|
||||||
if (with_lightning_infill)
|
if (with_lightning_infill)
|
||||||
{
|
{
|
||||||
const bool global_lightning_infill = true;
|
|
||||||
|
|
||||||
std::vector<Polygons> contours;
|
std::vector<Polygons> contours;
|
||||||
std::vector<Polygons> overhangs;
|
std::vector<Polygons> overhangs;
|
||||||
for (int layer_nr = 1; layer_nr < contact_nodes.size(); layer_nr++) {
|
for (int layer_nr = 1; layer_nr < contact_nodes.size(); layer_nr++) {
|
||||||
|
@ -2391,33 +2399,25 @@ void TreeSupport::draw_circles()
|
||||||
SupportLayer* lower_layer = m_object->get_support_layer(layer_nr_lower + m_raft_layers);
|
SupportLayer* lower_layer = m_object->get_support_layer(layer_nr_lower + m_raft_layers);
|
||||||
ExPolygons& base_areas_lower = lower_layer->base_areas;
|
ExPolygons& base_areas_lower = lower_layer->base_areas;
|
||||||
|
|
||||||
ExPolygons overhang;
|
ExPolygons overhang = diff_ex(offset_ex_2(base_areas_lower, -2.5 * line_width_scaled), base_areas);
|
||||||
if (global_lightning_infill)
|
for (auto it = overhang.begin(); it != overhang.end();) {
|
||||||
{
|
it->remove_colinear_points();
|
||||||
//search overhangs globally
|
if (it->empty())
|
||||||
overhang = std::move(diff_ex(offset_ex(base_areas_lower, -2.0 * scale_(support_extrusion_width)), base_areas));
|
it = overhang.erase(it);
|
||||||
}
|
else ++it;
|
||||||
else
|
|
||||||
{
|
|
||||||
//search overhangs only on floating islands
|
|
||||||
for (auto& base_area : base_areas)
|
|
||||||
for (auto& hole : base_area.holes)
|
|
||||||
{
|
|
||||||
Polygon rev_hole = hole;
|
|
||||||
rev_hole.make_counter_clockwise();
|
|
||||||
ExPolygons ex_hole;
|
|
||||||
ex_hole.emplace_back(std::move(ExPolygon(rev_hole)));
|
|
||||||
for (auto& other_area : base_areas)
|
|
||||||
//if (&other_area != &base_area)
|
|
||||||
ex_hole = std::move(diff_ex(ex_hole, other_area));
|
|
||||||
overhang = std::move(union_ex(overhang, ex_hole));
|
|
||||||
}
|
|
||||||
overhang = std::move(intersection_ex(overhang, offset_ex(base_areas_lower, -0.5 * scale_(support_extrusion_width))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
overhangs.emplace_back(to_polygons(overhang));
|
overhangs.emplace_back(to_polygons(overhang));
|
||||||
contours.emplace_back(to_polygons(base_areas_lower));
|
contours.emplace_back(to_polygons(base_areas_lower));
|
||||||
printZ_to_lightninglayer[lower_layer->print_z] = overhangs.size() - 1;
|
printZ_to_lightninglayer[lower_layer->print_z] = overhangs.size() - 1;
|
||||||
|
|
||||||
|
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
||||||
|
if (!overhang.empty() && !base_areas_lower.empty()) {
|
||||||
|
std::string fname = debug_out_path("lightning_%d_%.2f.svg", layer_nr, ts_layer->print_z);
|
||||||
|
SVG::export_expolygons(fname, {{base_areas_lower, {"base_areas_lower", "red", 0.5}}, {overhang, {"overhang", "blue", 0.5}}});
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3369,11 +3369,11 @@ void TreeSupport::smooth_nodes()
|
||||||
int idx_last_double_wall = -1;
|
int idx_last_double_wall = -1;
|
||||||
for (size_t i = 0; i < pts.size(); i++) {
|
for (size_t i = 0; i < pts.size(); i++) {
|
||||||
if (branch[i]->need_extra_wall) {
|
if (branch[i]->need_extra_wall) {
|
||||||
if (idx_first_double_wall < 0) idx_first_double_wall = i;
|
if (idx_first_double_wall < 0) idx_first_double_wall = i;
|
||||||
idx_last_double_wall = i;
|
idx_last_double_wall = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (idx_last_double_wall >= 0 && idx_first_double_wall >= 0 && idx_last_double_wall > idx_first_double_wall) {
|
if (idx_last_double_wall >= 0 && idx_first_double_wall >= 0 && idx_last_double_wall > idx_first_double_wall) {
|
||||||
for (size_t i = idx_first_double_wall + 1; i < idx_last_double_wall; i++) branch[i]->need_extra_wall = true;
|
for (size_t i = idx_first_double_wall + 1; i < idx_last_double_wall; i++) branch[i]->need_extra_wall = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3910,14 +3910,14 @@ TreeSupportData::TreeSupportData(const PrintObject &object, coordf_t xy_distance
|
||||||
ExPolygons &outline = m_layer_outlines[layer_nr];
|
ExPolygons &outline = m_layer_outlines[layer_nr];
|
||||||
outline.clear();
|
outline.clear();
|
||||||
outline.reserve(layer->lslices.size());
|
outline.reserve(layer->lslices.size());
|
||||||
for (const ExPolygon &poly : layer->lslices) { append(outline, union_ex2( poly.simplify_p(scale_(m_radius_sample_resolution)))); }
|
for (const ExPolygon &poly : layer->lslices) { append(outline, union_ex_2( poly.simplify_p(scale_(m_radius_sample_resolution)))); }
|
||||||
|
|
||||||
if (layer_nr == 0)
|
if (layer_nr == 0)
|
||||||
m_layer_outlines_below[layer_nr] = outline;
|
m_layer_outlines_below[layer_nr] = outline;
|
||||||
else {
|
else {
|
||||||
m_layer_outlines_below[layer_nr] = m_layer_outlines_below[layer_nr - 1];
|
m_layer_outlines_below[layer_nr] = m_layer_outlines_below[layer_nr - 1];
|
||||||
m_layer_outlines_below[layer_nr].insert(m_layer_outlines_below[layer_nr].end(), outline.begin(), outline.end());
|
m_layer_outlines_below[layer_nr].insert(m_layer_outlines_below[layer_nr].end(), outline.begin(), outline.end());
|
||||||
if (layer_nr % 10 == 0) m_layer_outlines_below[layer_nr] = union_ex2(m_layer_outlines_below[layer_nr]);
|
if (layer_nr % 10 == 0) m_layer_outlines_below[layer_nr] = union_ex_2(m_layer_outlines_below[layer_nr]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4032,6 +4032,10 @@ const ExPolygons& TreeSupportData::calculate_avoidance(const RadiusLayerPair& ke
|
||||||
avoidance_areas = std::move(union_ex(avoidance_areas));
|
avoidance_areas = std::move(union_ex(avoidance_areas));
|
||||||
auto ret = m_avoidance_cache.insert({key, std::move(avoidance_areas)});
|
auto ret = m_avoidance_cache.insert({key, std::move(avoidance_areas)});
|
||||||
//assert(ret.second);
|
//assert(ret.second);
|
||||||
|
// BOOST_LOG_TRIVIAL(debug) << format("calculate_avoidance: radius=%.2f, layer_nr=%d, recursions=%d, avoidance_areas=%d", radius, layer_nr, key.recursions,
|
||||||
|
// avoidance_areas.size());
|
||||||
|
// boost::log::core::get()->flush();
|
||||||
|
|
||||||
return ret.first->second;
|
return ret.first->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue