mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 15:15:54 +08:00
Fix of fuzzy skin
This commit is contained in:
parent
d971ed51a5
commit
61b3ca0b4b
@ -143,16 +143,19 @@ void Layer::make_perimeters()
|
|||||||
if (! (*it)->slices.empty()) {
|
if (! (*it)->slices.empty()) {
|
||||||
LayerRegion* other_layerm = *it;
|
LayerRegion* other_layerm = *it;
|
||||||
const PrintRegionConfig &other_config = other_layerm->region()->config();
|
const PrintRegionConfig &other_config = other_layerm->region()->config();
|
||||||
if (config.perimeter_extruder == other_config.perimeter_extruder
|
if (config.perimeter_extruder == other_config.perimeter_extruder
|
||||||
&& config.perimeters == other_config.perimeters
|
&& config.perimeters == other_config.perimeters
|
||||||
&& config.perimeter_speed == other_config.perimeter_speed
|
&& config.perimeter_speed == other_config.perimeter_speed
|
||||||
&& config.external_perimeter_speed == other_config.external_perimeter_speed
|
&& config.external_perimeter_speed == other_config.external_perimeter_speed
|
||||||
&& config.gap_fill_speed == other_config.gap_fill_speed
|
&& config.gap_fill_speed == other_config.gap_fill_speed
|
||||||
&& config.overhangs == other_config.overhangs
|
&& config.overhangs == other_config.overhangs
|
||||||
&& config.opt_serialize("perimeter_extrusion_width") == other_config.opt_serialize("perimeter_extrusion_width")
|
&& config.opt_serialize("perimeter_extrusion_width") == other_config.opt_serialize("perimeter_extrusion_width")
|
||||||
&& config.thin_walls == other_config.thin_walls
|
&& config.thin_walls == other_config.thin_walls
|
||||||
&& config.external_perimeters_first == other_config.external_perimeters_first
|
&& config.external_perimeters_first == other_config.external_perimeters_first
|
||||||
&& config.infill_overlap == other_config.infill_overlap)
|
&& config.infill_overlap == other_config.infill_overlap
|
||||||
|
&& config.fuzzy_skin == other_config.fuzzy_skin
|
||||||
|
&& config.fuzzy_skin_thickness == other_config.fuzzy_skin_thickness
|
||||||
|
&& config.fuzzy_skin_point_dist == other_config.fuzzy_skin_point_dist)
|
||||||
{
|
{
|
||||||
other_layerm->perimeters.clear();
|
other_layerm->perimeters.clear();
|
||||||
other_layerm->fills.clear();
|
other_layerm->fills.clear();
|
||||||
|
@ -112,30 +112,69 @@ static void variable_width(const ThickPolylines& polylines, ExtrusionRole role,
|
|||||||
class PerimeterGeneratorLoop {
|
class PerimeterGeneratorLoop {
|
||||||
public:
|
public:
|
||||||
// Polygon of this contour.
|
// Polygon of this contour.
|
||||||
Polygon polygon;
|
Polygon polygon;
|
||||||
// Is it a contour or a hole?
|
// Is it a contour or a hole?
|
||||||
// Contours are CCW oriented, holes are CW oriented.
|
// Contours are CCW oriented, holes are CW oriented.
|
||||||
bool is_contour;
|
bool is_contour;
|
||||||
// Depth in the hierarchy. External perimeter has depth = 0. An external perimeter could be both a contour and a hole.
|
// Depth in the hierarchy. External perimeter has depth = 0. An external perimeter could be both a contour and a hole.
|
||||||
unsigned short depth;
|
unsigned short depth;
|
||||||
|
// Should this contur be fuzzyfied on path generation?
|
||||||
|
bool fuzzify;
|
||||||
// Children contour, may be both CCW and CW oriented (outer contours or holes).
|
// Children contour, may be both CCW and CW oriented (outer contours or holes).
|
||||||
std::vector<PerimeterGeneratorLoop> children;
|
std::vector<PerimeterGeneratorLoop> children;
|
||||||
|
|
||||||
PerimeterGeneratorLoop(Polygon &&polygon, unsigned short depth, bool is_contour) :
|
PerimeterGeneratorLoop(const Polygon &polygon, unsigned short depth, bool is_contour, bool fuzzify) :
|
||||||
polygon(std::move(polygon)), is_contour(is_contour), depth(depth) {}
|
polygon(polygon), is_contour(is_contour), depth(depth), fuzzify(fuzzify) {}
|
||||||
// External perimeter. It may be CCW or CW oriented (outer contour or hole contour).
|
// External perimeter. It may be CCW or CW oriented (outer contour or hole contour).
|
||||||
bool is_external() const { return this->depth == 0; }
|
bool is_external() const { return this->depth == 0; }
|
||||||
// An island, which may have holes, but it does not have another internal island.
|
// An island, which may have holes, but it does not have another internal island.
|
||||||
bool is_internal_contour() const;
|
bool is_internal_contour() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<PerimeterGeneratorLoop> PerimeterGeneratorLoops;
|
// Thanks Cura developers for this function.
|
||||||
|
static void fuzzy_polygon(Polygon &poly, double fuzzy_skin_thickness, double fuzzy_skin_point_dist)
|
||||||
|
{
|
||||||
|
const double min_dist_between_points = fuzzy_skin_point_dist * 3. / 4.; // hardcoded: the point distance may vary between 3/4 and 5/4 the supplied value
|
||||||
|
const double range_random_point_dist = fuzzy_skin_point_dist / 2.;
|
||||||
|
double dist_left_over = double(rand()) * (min_dist_between_points / 2) / double(RAND_MAX); // the distance to be traversed on the line before making the first new point
|
||||||
|
Point* p0 = &poly.points.back();
|
||||||
|
Points out;
|
||||||
|
out.reserve(poly.points.size());
|
||||||
|
for (Point &p1 : poly.points)
|
||||||
|
{ // 'a' is the (next) new point between p0 and p1
|
||||||
|
Vec2d p0p1 = (p1 - *p0).cast<double>();
|
||||||
|
double p0p1_size = p0p1.norm();
|
||||||
|
// so that p0p1_size - dist_last_point evaulates to dist_left_over - p0p1_size
|
||||||
|
double dist_last_point = dist_left_over + p0p1_size * 2.;
|
||||||
|
for (double p0pa_dist = dist_left_over; p0pa_dist < p0p1_size;
|
||||||
|
p0pa_dist += min_dist_between_points + double(rand()) * range_random_point_dist / double(RAND_MAX))
|
||||||
|
{
|
||||||
|
double r = double(rand()) * (fuzzy_skin_thickness * 2.) / double(RAND_MAX) - fuzzy_skin_thickness;
|
||||||
|
out.emplace_back(*p0 + (p0p1 * (p0pa_dist / p0p1_size) + perp(p0p1).cast<double>().normalized() * r).cast<coord_t>());
|
||||||
|
dist_last_point = p0pa_dist;
|
||||||
|
}
|
||||||
|
dist_left_over = p0p1_size - dist_last_point;
|
||||||
|
p0 = &p1;
|
||||||
|
}
|
||||||
|
while (out.size() < 3) {
|
||||||
|
size_t point_idx = poly.size() - 2;
|
||||||
|
out.emplace_back(poly[point_idx]);
|
||||||
|
if (point_idx == 0)
|
||||||
|
break;
|
||||||
|
-- point_idx;
|
||||||
|
}
|
||||||
|
if (out.size() >= 3)
|
||||||
|
poly.points = std::move(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
using PerimeterGeneratorLoops = std::vector<PerimeterGeneratorLoop>;
|
||||||
|
|
||||||
static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perimeter_generator, const PerimeterGeneratorLoops &loops, ThickPolylines &thin_walls)
|
static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perimeter_generator, const PerimeterGeneratorLoops &loops, ThickPolylines &thin_walls)
|
||||||
{
|
{
|
||||||
// loops is an arrayref of ::Loop objects
|
// loops is an arrayref of ::Loop objects
|
||||||
// turn each one into an ExtrusionLoop object
|
// turn each one into an ExtrusionLoop object
|
||||||
ExtrusionEntityCollection coll;
|
ExtrusionEntityCollection coll;
|
||||||
|
Polygon fuzzified;
|
||||||
for (const PerimeterGeneratorLoop &loop : loops) {
|
for (const PerimeterGeneratorLoop &loop : loops) {
|
||||||
bool is_external = loop.is_external();
|
bool is_external = loop.is_external();
|
||||||
|
|
||||||
@ -153,12 +192,17 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
|
|||||||
|
|
||||||
// detect overhanging/bridging perimeters
|
// detect overhanging/bridging perimeters
|
||||||
ExtrusionPaths paths;
|
ExtrusionPaths paths;
|
||||||
|
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_dist.value));
|
||||||
|
}
|
||||||
if (perimeter_generator.config->overhangs && perimeter_generator.layer_id > 0
|
if (perimeter_generator.config->overhangs && perimeter_generator.layer_id > 0
|
||||||
&& !(perimeter_generator.object_config->support_material && perimeter_generator.object_config->support_material_contact_distance.value == 0)) {
|
&& !(perimeter_generator.object_config->support_material && perimeter_generator.object_config->support_material_contact_distance.value == 0)) {
|
||||||
// get non-overhang paths by intersecting this loop with the grown lower slices
|
// get non-overhang paths by intersecting this loop with the grown lower slices
|
||||||
extrusion_paths_append(
|
extrusion_paths_append(
|
||||||
paths,
|
paths,
|
||||||
intersection_pl((Polygons)loop.polygon, perimeter_generator.lower_slices_polygons()),
|
intersection_pl({ polygon }, perimeter_generator.lower_slices_polygons()),
|
||||||
role,
|
role,
|
||||||
is_external ? perimeter_generator.ext_mm3_per_mm() : perimeter_generator.mm3_per_mm(),
|
is_external ? perimeter_generator.ext_mm3_per_mm() : perimeter_generator.mm3_per_mm(),
|
||||||
is_external ? perimeter_generator.ext_perimeter_flow.width : perimeter_generator.perimeter_flow.width,
|
is_external ? perimeter_generator.ext_perimeter_flow.width : perimeter_generator.perimeter_flow.width,
|
||||||
@ -169,7 +213,7 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
|
|||||||
// the loop centerline and original lower slices is >= half nozzle diameter
|
// the loop centerline and original lower slices is >= half nozzle diameter
|
||||||
extrusion_paths_append(
|
extrusion_paths_append(
|
||||||
paths,
|
paths,
|
||||||
diff_pl((Polygons)loop.polygon, perimeter_generator.lower_slices_polygons()),
|
diff_pl({ polygon }, perimeter_generator.lower_slices_polygons()),
|
||||||
erOverhangPerimeter,
|
erOverhangPerimeter,
|
||||||
perimeter_generator.mm3_per_mm_overhang(),
|
perimeter_generator.mm3_per_mm_overhang(),
|
||||||
perimeter_generator.overhang_flow.width,
|
perimeter_generator.overhang_flow.width,
|
||||||
@ -180,7 +224,7 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
|
|||||||
chain_and_reorder_extrusion_paths(paths, &paths.front().first_point());
|
chain_and_reorder_extrusion_paths(paths, &paths.front().first_point());
|
||||||
} else {
|
} else {
|
||||||
ExtrusionPath path(role);
|
ExtrusionPath path(role);
|
||||||
path.polyline = loop.polygon.split_at_first_point();
|
path.polyline = polygon.split_at_first_point();
|
||||||
path.mm3_per_mm = is_external ? perimeter_generator.ext_mm3_per_mm() : perimeter_generator.mm3_per_mm();
|
path.mm3_per_mm = is_external ? perimeter_generator.ext_mm3_per_mm() : perimeter_generator.mm3_per_mm();
|
||||||
path.width = is_external ? perimeter_generator.ext_perimeter_flow.width : perimeter_generator.perimeter_flow.width;
|
path.width = is_external ? perimeter_generator.ext_perimeter_flow.width : perimeter_generator.perimeter_flow.width;
|
||||||
path.height = (float)perimeter_generator.layer_height;
|
path.height = (float)perimeter_generator.layer_height;
|
||||||
@ -230,42 +274,6 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Thanks Cura developers for this function.
|
|
||||||
static void fuzzy_polygon(Polygon &poly, double fuzzy_skin_thickness, double fuzzy_skin_point_dist)
|
|
||||||
{
|
|
||||||
const double min_dist_between_points = fuzzy_skin_point_dist * 3. / 4.; // hardcoded: the point distance may vary between 3/4 and 5/4 the supplied value
|
|
||||||
const double range_random_point_dist = fuzzy_skin_point_dist / 2.;
|
|
||||||
double dist_left_over = double(rand()) * (min_dist_between_points / 2) / double(RAND_MAX); // the distance to be traversed on the line before making the first new point
|
|
||||||
Point* p0 = &poly.points.back();
|
|
||||||
Points out;
|
|
||||||
out.reserve(poly.points.size());
|
|
||||||
for (Point &p1 : poly.points)
|
|
||||||
{ // 'a' is the (next) new point between p0 and p1
|
|
||||||
Vec2d p0p1 = (p1 - *p0).cast<double>();
|
|
||||||
double p0p1_size = p0p1.norm();
|
|
||||||
// so that p0p1_size - dist_last_point evaulates to dist_left_over - p0p1_size
|
|
||||||
double dist_last_point = dist_left_over + p0p1_size * 2.;
|
|
||||||
for (double p0pa_dist = dist_left_over; p0pa_dist < p0p1_size;
|
|
||||||
p0pa_dist += min_dist_between_points + double(rand()) * range_random_point_dist / double(RAND_MAX))
|
|
||||||
{
|
|
||||||
double r = double(rand()) * (fuzzy_skin_thickness * 2.) / double(RAND_MAX) - fuzzy_skin_thickness;
|
|
||||||
out.emplace_back(*p0 + (p0p1 * (p0pa_dist / p0p1_size) + perp(p0p1).cast<double>().normalized() * r).cast<coord_t>());
|
|
||||||
dist_last_point = p0pa_dist;
|
|
||||||
}
|
|
||||||
dist_left_over = p0p1_size - dist_last_point;
|
|
||||||
p0 = &p1;
|
|
||||||
}
|
|
||||||
while (out.size() < 3) {
|
|
||||||
size_t point_idx = poly.size() - 2;
|
|
||||||
out.emplace_back(poly[point_idx]);
|
|
||||||
if (point_idx == 0)
|
|
||||||
break;
|
|
||||||
-- point_idx;
|
|
||||||
}
|
|
||||||
if (out.size() >= 3)
|
|
||||||
poly.points = std::move(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PerimeterGenerator::process()
|
void PerimeterGenerator::process()
|
||||||
{
|
{
|
||||||
// other perimeters
|
// other perimeters
|
||||||
@ -392,27 +400,22 @@ void PerimeterGenerator::process()
|
|||||||
// If i > loop_number, we were looking just for gaps.
|
// If i > loop_number, we were looking just for gaps.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const bool fuzzify = this->config->fuzzy_skin != FuzzySkinType::None && i == 0 && this->layer_id > 0;
|
{
|
||||||
for (ExPolygon expolygon : offsets) {
|
const bool fuzzify_contours = this->config->fuzzy_skin != FuzzySkinType::None && i == 0 && this->layer_id > 0;
|
||||||
// Outer contour may overlap with an inner contour,
|
const bool fuzzify_holes = fuzzify_contours && this->config->fuzzy_skin == FuzzySkinType::All;
|
||||||
// inner contour may overlap with another inner contour,
|
for (const ExPolygon &expolygon : offsets) {
|
||||||
// outer contour may overlap with itself.
|
// Outer contour may overlap with an inner contour,
|
||||||
//FIXME evaluate the overlaps, annotate each point with an overlap depth,
|
// inner contour may overlap with another inner contour,
|
||||||
if (fuzzify) {
|
// outer contour may overlap with itself.
|
||||||
// External perimeter, above the 1st layer.
|
//FIXME evaluate the overlaps, annotate each point with an overlap depth,
|
||||||
fuzzy_polygon(expolygon.contour, fuzzy_skin_thickness, fuzzy_skin_point_dist);
|
// compensate for the depth of intersection.
|
||||||
if (this->config->fuzzy_skin == FuzzySkinType::All)
|
contours[i].emplace_back(expolygon.contour, i, true, fuzzify_contours);
|
||||||
for (Polygon &hole : expolygon.holes)
|
|
||||||
fuzzy_polygon(hole, fuzzy_skin_thickness, fuzzy_skin_point_dist);
|
|
||||||
}
|
|
||||||
|
|
||||||
// compensate for the depth of intersection.
|
if (! expolygon.holes.empty()) {
|
||||||
contours[i].emplace_back(std::move(expolygon.contour), i, true);
|
holes[i].reserve(holes[i].size() + expolygon.holes.size());
|
||||||
|
for (const Polygon &hole : expolygon.holes)
|
||||||
if (! expolygon.holes.empty()) {
|
holes[i].emplace_back(hole, i, false, fuzzify_holes);
|
||||||
holes[i].reserve(holes[i].size() + expolygon.holes.size());
|
}
|
||||||
for (Polygon &hole : expolygon.holes)
|
|
||||||
holes[i].emplace_back(std::move(hole), i, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
last = std::move(offsets);
|
last = std::move(offsets);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user