mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-14 02:07:54 -06:00
Squashed commit of the following:
commit 61b3ca0b4b4a0b4cfbbc706ede94ef7ccec4c91f Author: Vojtech Bubnik <bubnikv@gmail.com> Date: Wed Feb 10 15:42:27 2021 +0100 Fix of fuzzy skin commit d971ed51a5bb65e8bdfd326bc41b9d7ab2e20834 Author: Vojtech Bubnik <bubnikv@gmail.com> Date: Wed Feb 10 14:12:51 2021 +0100 CMake adjustment of MINIMUM_BOOST_VERSION commit 5d8aa2c59ecf7e32456f2e43e07dedc7d24eb21c Author: Vojtech Bubnik <bubnikv@gmail.com> Date: Wed Feb 10 14:12:33 2021 +0100 Fix of debug compilation after warning removal. commit 5e339b3078f0c9d75b6fac28ed3c295ae9fbbef5 Author: Vojtech Bubnik <bubnikv@gmail.com> Date: Wed Feb 10 14:11:34 2021 +0100 Fuzzy Skin changes: 1) Moved the parameters to region 2) Removed experimental code. 3) Allowed fuzzyfication of both outer perimeter and holes.
This commit is contained in:
parent
f639c08caf
commit
6555b32f5c
12 changed files with 118 additions and 312 deletions
|
@ -5,7 +5,6 @@
|
|||
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
@ -113,30 +112,69 @@ static void variable_width(const ThickPolylines& polylines, ExtrusionRole role,
|
|||
class PerimeterGeneratorLoop {
|
||||
public:
|
||||
// Polygon of this contour.
|
||||
Polygon polygon;
|
||||
Polygon polygon;
|
||||
// Is it a contour or a hole?
|
||||
// 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.
|
||||
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).
|
||||
std::vector<PerimeterGeneratorLoop> children;
|
||||
|
||||
PerimeterGeneratorLoop(Polygon polygon, unsigned short depth, bool is_contour) :
|
||||
polygon(polygon), is_contour(is_contour), depth(depth) {}
|
||||
PerimeterGeneratorLoop(const Polygon &polygon, unsigned short depth, bool is_contour, bool fuzzify) :
|
||||
polygon(polygon), is_contour(is_contour), depth(depth), fuzzify(fuzzify) {}
|
||||
// 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;
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
// loops is an arrayref of ::Loop objects
|
||||
// turn each one into an ExtrusionLoop object
|
||||
ExtrusionEntityCollection coll;
|
||||
ExtrusionEntityCollection coll;
|
||||
Polygon fuzzified;
|
||||
for (const PerimeterGeneratorLoop &loop : loops) {
|
||||
bool is_external = loop.is_external();
|
||||
|
||||
|
@ -154,12 +192,17 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
|
|||
|
||||
// detect overhanging/bridging perimeters
|
||||
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
|
||||
&& !(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
|
||||
extrusion_paths_append(
|
||||
paths,
|
||||
intersection_pl((Polygons)loop.polygon, perimeter_generator.lower_slices_polygons()),
|
||||
intersection_pl({ polygon }, perimeter_generator.lower_slices_polygons()),
|
||||
role,
|
||||
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,
|
||||
|
@ -170,7 +213,7 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
|
|||
// the loop centerline and original lower slices is >= half nozzle diameter
|
||||
extrusion_paths_append(
|
||||
paths,
|
||||
diff_pl((Polygons)loop.polygon, perimeter_generator.lower_slices_polygons()),
|
||||
diff_pl({ polygon }, perimeter_generator.lower_slices_polygons()),
|
||||
erOverhangPerimeter,
|
||||
perimeter_generator.mm3_per_mm_overhang(),
|
||||
perimeter_generator.overhang_flow.width,
|
||||
|
@ -181,7 +224,7 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
|
|||
chain_and_reorder_extrusion_paths(paths, &paths.front().first_point());
|
||||
} else {
|
||||
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.width = is_external ? perimeter_generator.ext_perimeter_flow.width : perimeter_generator.perimeter_flow.width;
|
||||
path.height = (float)perimeter_generator.layer_height;
|
||||
|
@ -231,130 +274,8 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
|
|||
return out;
|
||||
}
|
||||
|
||||
/*
|
||||
enum class FuzzyShape {
|
||||
Triangle,
|
||||
Sawtooth,
|
||||
Random
|
||||
};
|
||||
*/
|
||||
|
||||
static void fuzzy_polygon(Polygon &poly, /* FuzzyShape shape, */ double fuzzy_skin_thickness, double fuzzy_skin_point_dist)
|
||||
{
|
||||
#if 0
|
||||
Point last = poly.points.at(poly.points.size() - 1);
|
||||
Point last_processed = last;
|
||||
|
||||
double max_length = scale_(2);
|
||||
double min_length = scale_(1);
|
||||
|
||||
if (poly.length() < scale_(5))
|
||||
return;
|
||||
|
||||
deepness *= 3;
|
||||
|
||||
bool triangle_or_sawtooth = shape == FuzzyShape::Sawtooth;
|
||||
double length_sum = 0;
|
||||
Points::iterator it = poly.points.begin();
|
||||
while (it != poly.points.end()) {
|
||||
Point &pt = *it;
|
||||
|
||||
Line line(last, pt);
|
||||
double length = line.length();
|
||||
|
||||
// split long line
|
||||
if (length > max_length) {
|
||||
auto parts = int(ceil(length / max_length));
|
||||
if (parts == 2) {
|
||||
Point point_to_insert(line.midpoint());
|
||||
it = poly.points.insert(it, point_to_insert);
|
||||
}
|
||||
else {
|
||||
Vector part_vector = line.vector() / parts;
|
||||
|
||||
Points points_to_insert;
|
||||
Point point_to_insert(last);
|
||||
while (--parts) {
|
||||
point_to_insert += part_vector;
|
||||
Point point_to_insert_2(point_to_insert);
|
||||
points_to_insert.push_back(point_to_insert_2);
|
||||
}
|
||||
|
||||
it = poly.points.insert(it, points_to_insert.begin(), points_to_insert.end());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
length_sum += length;
|
||||
|
||||
// join short lines
|
||||
if (length_sum < min_length) {
|
||||
last = pt;
|
||||
it = poly.points.erase(it);
|
||||
continue;
|
||||
}
|
||||
|
||||
line = Line(last_processed, pt);
|
||||
last = pt;
|
||||
last_processed = pt;
|
||||
|
||||
if (shape == FuzzyShape::Random) {
|
||||
triangle_or_sawtooth = !(rand() % 2);
|
||||
}
|
||||
|
||||
Point point_to_insert(triangle_or_sawtooth ? pt : line.midpoint());
|
||||
|
||||
int scale = (rand() % deepness) + 1;
|
||||
|
||||
Vec2d normal = line.normal().cast<double>();
|
||||
normal /= line.length() / scale_(1.) / ((double)scale / 20.);
|
||||
|
||||
it = poly.points.insert(it, point_to_insert + normal.cast<coord_t>()) + 2;
|
||||
|
||||
length_sum = 0;
|
||||
}
|
||||
|
||||
#else
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
|
||||
void PerimeterGenerator::process()
|
||||
{
|
||||
// nasty hack! initialize random generator
|
||||
auto time_us = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now()).time_since_epoch()).count();
|
||||
srand(this->layer_id * time_us);
|
||||
|
||||
// other perimeters
|
||||
m_mm3_per_mm = this->perimeter_flow.mm3_per_mm();
|
||||
coord_t perimeter_width = this->perimeter_flow.scaled_width();
|
||||
|
@ -396,30 +317,8 @@ void PerimeterGenerator::process()
|
|||
}
|
||||
|
||||
// fuzzy skin configuration
|
||||
double fuzzy_skin_thickness = scale_(this->object_config->fuzzy_skin_thickness);
|
||||
double fuzzy_skin_point_dist = scale_(this->object_config->fuzzy_skin_point_dist);
|
||||
//FuzzyShape fuzzy_skin_shape;
|
||||
if (this->object_config->fuzzy_skin_perimeter_mode != FuzzySkinPerimeterMode::None) {
|
||||
/*
|
||||
switch (this->object_config->fuzzy_skin_shape) {
|
||||
case FuzzySkinShape::Triangle1:
|
||||
case FuzzySkinShape::Triangle2:
|
||||
case FuzzySkinShape::Triangle3:
|
||||
fuzzy_skin_shape = FuzzyShape::Triangle;
|
||||
break;
|
||||
case FuzzySkinShape::Sawtooth1:
|
||||
case FuzzySkinShape::Sawtooth2:
|
||||
case FuzzySkinShape::Sawtooth3:
|
||||
fuzzy_skin_shape = FuzzyShape::Sawtooth;
|
||||
break;
|
||||
case FuzzySkinShape::Random1:
|
||||
case FuzzySkinShape::Random2:
|
||||
case FuzzySkinShape::Random3:
|
||||
fuzzy_skin_shape = FuzzyShape::Random;
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
double fuzzy_skin_thickness = scale_(this->config->fuzzy_skin_thickness);
|
||||
double fuzzy_skin_point_dist = scale_(this->config->fuzzy_skin_point_dist);
|
||||
|
||||
// we need to process each island separately because we might have different
|
||||
// extra perimeters for each one
|
||||
|
@ -501,39 +400,22 @@ void PerimeterGenerator::process()
|
|||
// If i > loop_number, we were looking just for gaps.
|
||||
break;
|
||||
}
|
||||
for (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,
|
||||
|
||||
bool skip_polygon = false;
|
||||
|
||||
if (this->object_config->fuzzy_skin_perimeter_mode != FuzzySkinPerimeterMode::None) {
|
||||
if (i == 0 && (this->object_config->fuzzy_skin_perimeter_mode != FuzzySkinPerimeterMode::ExternalSkipFirst || this->layer_id > 0)) {
|
||||
if (
|
||||
this->object_config->fuzzy_skin_perimeter_mode == FuzzySkinPerimeterMode::External ||
|
||||
this->object_config->fuzzy_skin_perimeter_mode == FuzzySkinPerimeterMode::ExternalSkipFirst
|
||||
) {
|
||||
ExPolygon expolygon_fuzzy(expolygon);
|
||||
fuzzy_polygon(expolygon_fuzzy.contour, /* fuzzy_skin_shape, */ fuzzy_skin_thickness, fuzzy_skin_point_dist);
|
||||
// compensate for the depth of intersection.
|
||||
contours[i].emplace_back(PerimeterGeneratorLoop(expolygon_fuzzy.contour, i, true));
|
||||
skip_polygon = true;
|
||||
} else
|
||||
fuzzy_polygon(expolygon.contour, /* fuzzy_skin_shape, */ fuzzy_skin_thickness, fuzzy_skin_point_dist);
|
||||
}
|
||||
}
|
||||
|
||||
if (!skip_polygon) {
|
||||
{
|
||||
const bool fuzzify_contours = this->config->fuzzy_skin != FuzzySkinType::None && i == 0 && this->layer_id > 0;
|
||||
const bool fuzzify_holes = fuzzify_contours && this->config->fuzzy_skin == FuzzySkinType::All;
|
||||
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));
|
||||
}
|
||||
contours[i].emplace_back(expolygon.contour, i, true, fuzzify_contours);
|
||||
|
||||
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));
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
last = std::move(offsets);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue