mirror of
https://github.com/QIDITECH/QIDIStudio.git
synced 2026-02-07 04:11:50 +03:00
update libslic3r
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
#include <thread>
|
||||
#include <unordered_set>
|
||||
#include "OverhangDetector.hpp"
|
||||
#include "FuzzySkin.hpp"
|
||||
|
||||
static const double narrow_loop_length_threshold = 10;
|
||||
//QDS: when the width of expolygon is smaller than
|
||||
@@ -44,21 +45,20 @@ public:
|
||||
bool is_smaller_width_perimeter;
|
||||
// Depth in the hierarchy. External perimeter has depth = 0. An external perimeter could be both a contour and a hole.
|
||||
unsigned short depth;
|
||||
// Should this contur be fuzzyfied on path generation?
|
||||
bool fuzzify;
|
||||
// Slow down speed for circle
|
||||
bool need_circle_compensation = false;
|
||||
// Children contour, may be both CCW and CW oriented (outer contours or holes).
|
||||
std::vector<PerimeterGeneratorLoop> children;
|
||||
|
||||
PerimeterGeneratorLoop(const Polygon &polygon, unsigned short depth, bool is_contour, bool fuzzify, bool is_small_width_perimeter = false, bool need_circle_compensation_ = false) :
|
||||
polygon(polygon), is_contour(is_contour), is_smaller_width_perimeter(is_small_width_perimeter), depth(depth), fuzzify(fuzzify), need_circle_compensation(need_circle_compensation_) {}
|
||||
PerimeterGeneratorLoop(const Polygon &polygon, unsigned short depth, bool is_contour, bool is_small_width_perimeter = false, bool need_circle_compensation_ = false) :
|
||||
polygon(polygon), is_contour(is_contour), is_smaller_width_perimeter(is_small_width_perimeter), depth(depth), need_circle_compensation(need_circle_compensation_) {}
|
||||
// External perimeter. It may be CCW or CW oriented (outer contour or hole contour).
|
||||
bool is_external() const { return this->depth == 0; }
|
||||
// An island, which may have holes, but it does not have another internal island.
|
||||
bool is_internal_contour() const;
|
||||
};
|
||||
|
||||
#if 0
|
||||
// Thanks Cura developers for this function.
|
||||
static void fuzzy_polygon(Polygon &poly, double fuzzy_skin_thickness, double fuzzy_skin_point_distance)
|
||||
{
|
||||
@@ -138,7 +138,7 @@ static void fuzzy_extrusion_line(Arachne::ExtrusionLine& ext_lines, double fuzzy
|
||||
if (out.size() >= 3)
|
||||
ext_lines.junctions = std::move(out);
|
||||
}
|
||||
|
||||
#endif
|
||||
using PerimeterGeneratorLoops = std::vector<PerimeterGeneratorLoop>;
|
||||
|
||||
static void lowpass_filter_by_paths_overhang_degree(ExtrusionPaths& paths) {
|
||||
@@ -454,7 +454,6 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
|
||||
// loops is an arrayref of ::Loop objects
|
||||
// turn each one into an ExtrusionLoop object
|
||||
ExtrusionEntityCollection coll;
|
||||
Polygon fuzzified;
|
||||
for (const PerimeterGeneratorLoop &loop : loops) {
|
||||
bool is_external = loop.is_external();
|
||||
bool is_small_width = loop.is_smaller_width_perimeter;
|
||||
@@ -509,12 +508,10 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
|
||||
extrusion_width = perimeter_generator.perimeter_flow.width();
|
||||
}
|
||||
|
||||
// Apply fuzzy skin if it is enabled for at least some part of the polygon.
|
||||
const Polygon polygon = apply_fuzzy_skin(loop.polygon, *(perimeter_generator.config), *(perimeter_generator.perimeter_regions),
|
||||
perimeter_generator.layer_id, loop.depth, loop.is_contour);
|
||||
|
||||
const Polygon &polygon = loop.fuzzify ? fuzzified : loop.polygon;
|
||||
if (loop.fuzzify) {
|
||||
fuzzified = loop.polygon;
|
||||
fuzzy_polygon(fuzzified, scaled<float>(perimeter_generator.config->fuzzy_skin_thickness.value), scaled<float>(perimeter_generator.config->fuzzy_skin_point_distance.value));
|
||||
}
|
||||
if (perimeter_generator.config->detect_overhang_wall && perimeter_generator.layer_id > perimeter_generator.object_config->raft_layers) {
|
||||
// get non 100% overhang paths by intersecting this loop with the grown lower slices
|
||||
// prepare grown lower layer slices for overhang detection
|
||||
@@ -534,22 +531,6 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
|
||||
bool detect_overhang_degree = perimeter_generator.config->enable_overhang_speed.get_at(get_extruder_index(*(perimeter_generator.print_config), perimeter_generator.config->wall_filament - 1))
|
||||
&& perimeter_generator.config->fuzzy_skin == FuzzySkinType::None;
|
||||
|
||||
//QDS: fuzziy skin may generate a line that approximates a point, which can cause the clipper to get empty results
|
||||
if (loop.fuzzify && remain_polines.empty() && inside_polines.empty()) {
|
||||
bool inside_contour = false;
|
||||
for (const Polygon cliped_polygon : lower_polygons_series_clipped) {
|
||||
if (cliped_polygon.contains(polygon.first_point())) {
|
||||
inside_contour = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (inside_contour)
|
||||
inside_polines.push_back(to_polyline(polygon));
|
||||
else
|
||||
remain_polines.push_back(to_polyline(polygon));
|
||||
}
|
||||
|
||||
if (!detect_overhang_degree) {
|
||||
if (!inside_polines.empty())
|
||||
extrusion_paths_append(
|
||||
@@ -597,12 +578,14 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// get 100% overhang paths by checking what parts of this loop fall
|
||||
// outside the grown lower slices (thus where the distance between
|
||||
// the loop centerline and original lower slices is >= half nozzle diameter
|
||||
if (remain_polines.size() != 0) {
|
||||
if (!((perimeter_generator.object_config->enable_support || perimeter_generator.object_config->enforce_support_layers > 0)
|
||||
&& perimeter_generator.object_config->support_top_z_distance.value == 0)) {
|
||||
if (!((perimeter_generator.object_config->enable_support || perimeter_generator.object_config->enforce_support_layers > 0) &&
|
||||
perimeter_generator.object_config->support_top_z_distance.value == 0) &&
|
||||
detect_overhang_degree) {
|
||||
//detect if the overhang perimeter is bridge
|
||||
detect_bridge_wall(perimeter_generator,
|
||||
paths,
|
||||
@@ -623,6 +606,9 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
|
||||
|
||||
}
|
||||
|
||||
if (paths.empty())
|
||||
continue;
|
||||
|
||||
// Reapply the nearest point search for starting point.
|
||||
// We allow polyline reversal because Clipper may have randomly reversed polylines during clipping.
|
||||
chain_and_reorder_extrusion_paths(paths, &paths.front().first_point());
|
||||
@@ -847,8 +833,9 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator& p
|
||||
perimeter_generator.loop_nodes->push_back(std::move(node));
|
||||
}
|
||||
|
||||
if (pg_extrusion.fuzzify)
|
||||
fuzzy_extrusion_line(*extrusion, scaled<float>(perimeter_generator.config->fuzzy_skin_thickness.value), scaled<float>(perimeter_generator.config->fuzzy_skin_point_distance.value));
|
||||
// Apply fuzzy skin if it is enabled for at least some part of the ExtrusionLine.
|
||||
*extrusion = apply_fuzzy_skin(*extrusion, *(perimeter_generator.config), *(perimeter_generator.perimeter_regions), perimeter_generator.layer_id,
|
||||
pg_extrusion.extrusion->inset_idx, !pg_extrusion.extrusion->is_closed || pg_extrusion.is_contour);
|
||||
|
||||
ExtrusionPaths paths;
|
||||
// detect overhanging/bridging perimeters
|
||||
@@ -1245,19 +1232,17 @@ void PerimeterGenerator::process_classic()
|
||||
break;
|
||||
}
|
||||
{
|
||||
const bool fuzzify_contours = this->config->fuzzy_skin != FuzzySkinType::None && ((i == 0 && this->layer_id > 0) || this->config->fuzzy_skin == FuzzySkinType::AllWalls);
|
||||
const bool fuzzify_holes = fuzzify_contours && (this->config->fuzzy_skin == FuzzySkinType::All || this->config->fuzzy_skin == FuzzySkinType::AllWalls);
|
||||
for (const ExPolygon& expolygon : offsets) {
|
||||
// Outer contour may overlap with an inner contour,
|
||||
// inner contour may overlap with another inner contour,
|
||||
// outer contour may overlap with itself.
|
||||
//FIXME evaluate the overlaps, annotate each point with an overlap depth,
|
||||
// compensate for the depth of intersection.
|
||||
contours[i].emplace_back(PerimeterGeneratorLoop(expolygon.contour, i, true, fuzzify_contours, false, counter_circle_compensation));
|
||||
contours[i].emplace_back(PerimeterGeneratorLoop(expolygon.contour, i, true, false, counter_circle_compensation));
|
||||
if (!expolygon.holes.empty()) {
|
||||
holes[i].reserve(holes[i].size() + expolygon.holes.size());
|
||||
for (const Polygon &hole : expolygon.holes)
|
||||
holes[i].emplace_back(hole, i, false, fuzzify_holes, false, is_compensation_hole(hole));
|
||||
holes[i].emplace_back(hole, i, false, false, is_compensation_hole(hole));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1293,11 +1278,11 @@ void PerimeterGenerator::process_classic()
|
||||
}
|
||||
|
||||
for (const ExPolygon& expolygon : offsets_with_smaller_width) {
|
||||
contours[i].emplace_back(PerimeterGeneratorLoop(expolygon.contour, i, true, fuzzify_contours, true, counter_circle_compensation));
|
||||
contours[i].emplace_back(PerimeterGeneratorLoop(expolygon.contour, i, true, true, counter_circle_compensation));
|
||||
if (!expolygon.holes.empty()) {
|
||||
holes[i].reserve(holes[i].size() + expolygon.holes.size());
|
||||
for (const Polygon& hole : expolygon.holes)
|
||||
holes[i].emplace_back(PerimeterGeneratorLoop(hole, i, false, fuzzify_contours, true, is_compensation_hole(hole)));
|
||||
holes[i].emplace_back(PerimeterGeneratorLoop(hole, i, false, true, is_compensation_hole(hole)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1934,46 +1919,6 @@ void PerimeterGenerator::process_arachne()
|
||||
}
|
||||
}
|
||||
|
||||
if (this->layer_id > 0 && this->config->fuzzy_skin != FuzzySkinType::None) {
|
||||
std::vector<PerimeterGeneratorArachneExtrusion*> closed_loop_extrusions;
|
||||
for (PerimeterGeneratorArachneExtrusion& extrusion : ordered_extrusions)
|
||||
if (extrusion.extrusion->inset_idx == 0) {
|
||||
if (extrusion.extrusion->is_closed && this->config->fuzzy_skin == FuzzySkinType::External) {
|
||||
closed_loop_extrusions.emplace_back(&extrusion);
|
||||
}
|
||||
else {
|
||||
extrusion.fuzzify = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->config->fuzzy_skin == FuzzySkinType::External) {
|
||||
ClipperLib_Z::Paths loops_paths;
|
||||
loops_paths.reserve(closed_loop_extrusions.size());
|
||||
for (const auto& cl_extrusion : closed_loop_extrusions) {
|
||||
assert(cl_extrusion->extrusion->junctions.front() == cl_extrusion->extrusion->junctions.back());
|
||||
size_t loop_idx = &cl_extrusion - &closed_loop_extrusions.front();
|
||||
ClipperLib_Z::Path loop_path;
|
||||
loop_path.reserve(cl_extrusion->extrusion->junctions.size() - 1);
|
||||
for (auto junction_it = cl_extrusion->extrusion->junctions.begin(); junction_it != std::prev(cl_extrusion->extrusion->junctions.end()); ++junction_it)
|
||||
loop_path.emplace_back(junction_it->p.x(), junction_it->p.y(), loop_idx);
|
||||
loops_paths.emplace_back(loop_path);
|
||||
}
|
||||
|
||||
ClipperLib_Z::Clipper clipper;
|
||||
clipper.AddPaths(loops_paths, ClipperLib_Z::ptSubject, true);
|
||||
ClipperLib_Z::PolyTree loops_polytree;
|
||||
clipper.Execute(ClipperLib_Z::ctUnion, loops_polytree, ClipperLib_Z::pftEvenOdd, ClipperLib_Z::pftEvenOdd);
|
||||
|
||||
for (const ClipperLib_Z::PolyNode* child_node : loops_polytree.Childs) {
|
||||
// The whole contour must have the same index.
|
||||
coord_t polygon_idx = child_node->Contour.front().z();
|
||||
bool has_same_idx = std::all_of(child_node->Contour.begin(), child_node->Contour.end(),
|
||||
[&polygon_idx](const ClipperLib_Z::IntPoint& point) -> bool { return polygon_idx == point.z(); });
|
||||
if (has_same_idx)
|
||||
closed_loop_extrusions[polygon_idx]->fuzzify = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// QDS. adjust wall generate seq
|
||||
if (this->object_config->wall_sequence == WallSequence::InnerOuterInner) {
|
||||
if (ordered_extrusions.size() > 2) { // 3 walls minimum needed to do inner outer inner ordering
|
||||
@@ -2092,4 +2037,38 @@ std::vector<Polygons> PerimeterGenerator::generate_lower_polygons_series(float w
|
||||
return lower_polygons_series;
|
||||
}
|
||||
|
||||
PerimeterRegion::PerimeterRegion(const LayerRegion &layer_region) : region(&layer_region.region())
|
||||
{
|
||||
this->expolygons = to_expolygons(layer_region.slices.surfaces);
|
||||
this->bbox = get_extents(this->expolygons);
|
||||
}
|
||||
|
||||
bool PerimeterRegion::has_compatible_perimeter_regions(const PrintRegionConfig &config, const PrintRegionConfig &other_config)
|
||||
{
|
||||
return config.fuzzy_skin == other_config.fuzzy_skin && config.fuzzy_skin_thickness == other_config.fuzzy_skin_thickness
|
||||
&& config.fuzzy_skin_point_distance == other_config.fuzzy_skin_point_distance;
|
||||
}
|
||||
|
||||
void PerimeterRegion::merge_compatible_perimeter_regions(PerimeterRegions &perimeter_regions)
|
||||
{
|
||||
if (perimeter_regions.size() <= 1) { return; }
|
||||
|
||||
PerimeterRegions perimeter_regions_merged;
|
||||
for (auto it_curr_region = perimeter_regions.begin(); it_curr_region != perimeter_regions.end();) {
|
||||
PerimeterRegion current_merge = *it_curr_region;
|
||||
auto it_next_region = std::next(it_curr_region);
|
||||
for (; it_next_region != perimeter_regions.end() && has_compatible_perimeter_regions(it_next_region->region->config(), it_curr_region->region->config());
|
||||
++it_next_region) {
|
||||
Slic3r::append(current_merge.expolygons, std::move(it_next_region->expolygons));
|
||||
current_merge.bbox.merge(it_next_region->bbox);
|
||||
}
|
||||
|
||||
if (std::distance(it_curr_region, it_next_region) > 1) { current_merge.expolygons = union_ex(current_merge.expolygons); }
|
||||
|
||||
perimeter_regions_merged.emplace_back(std::move(current_merge));
|
||||
it_curr_region = it_next_region;
|
||||
}
|
||||
|
||||
perimeter_regions = perimeter_regions_merged;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user