Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_custom_gcode_detection

This commit is contained in:
enricoturri1966 2021-04-21 12:32:17 +02:00
commit c7771a576b
73 changed files with 2263 additions and 2165 deletions

View file

@ -40,7 +40,7 @@ void BridgeDetector::initialize()
this->angle = -1.;
// Outset our bridge by an arbitrary amout; we'll use this outer margin for detecting anchors.
Polygons grown = offset(to_polygons(this->expolygons), float(this->spacing));
Polygons grown = offset(this->expolygons, float(this->spacing));
// Detect possible anchoring edges of this bridging region.
// Detect what edges lie on lower slices by turning bridge contour and holes

View file

@ -57,6 +57,7 @@ err:
}
#endif /* CLIPPER_UTILS_DEBUG */
#ifdef CLIPPERUTILS_OFFSET_SCALE
void scaleClipperPolygon(ClipperLib::Path &polygon)
{
CLIPPERUTILS_PROFILE_FUNC();
@ -98,6 +99,7 @@ void unscaleClipperPolygons(ClipperLib::Paths &polygons)
pit->Y >>= CLIPPER_OFFSET_POWER_OF_2;
}
}
#endif // CLIPPERUTILS_OFFSET_SCALE
//-----------------------------------------------------------
// legacy code from Clipper documentation
@ -222,8 +224,10 @@ ClipperLib::Paths Slic3rMultiPoints_to_ClipperPaths(const Polylines &input)
ClipperLib::Paths _offset(ClipperLib::Paths &&input, ClipperLib::EndType endType, const float delta, ClipperLib::JoinType joinType, double miterLimit)
{
#ifdef CLIPPERUTILS_OFFSET_SCALE
// scale input
scaleClipperPolygons(input);
#endif // CLIPPERUTILS_OFFSET_SCALE
// perform offset
ClipperLib::ClipperOffset co;
@ -231,14 +235,20 @@ ClipperLib::Paths _offset(ClipperLib::Paths &&input, ClipperLib::EndType endType
co.ArcTolerance = miterLimit;
else
co.MiterLimit = miterLimit;
#ifdef CLIPPERUTILS_OFFSET_SCALE
float delta_scaled = delta * float(CLIPPER_OFFSET_SCALE);
#else // CLIPPERUTILS_OFFSET_SCALE
float delta_scaled = delta;
#endif // CLIPPERUTILS_OFFSET_SCALE
co.ShortestEdgeLength = double(std::abs(delta_scaled * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR));
co.AddPaths(input, joinType, endType);
ClipperLib::Paths retval;
co.Execute(retval, delta_scaled);
#ifdef CLIPPERUTILS_OFFSET_SCALE
// unscale output
unscaleClipperPolygons(retval);
#endif // CLIPPERUTILS_OFFSET_SCALE
return retval;
}
@ -257,14 +267,24 @@ ClipperLib::Paths _offset(const Slic3r::ExPolygon &expolygon, const float delta,
{
// printf("new ExPolygon offset\n");
// 1) Offset the outer contour.
const float delta_scaled = delta * float(CLIPPER_OFFSET_SCALE);
#ifdef CLIPPERUTILS_OFFSET_SCALE
float delta_scaled = delta * float(CLIPPER_OFFSET_SCALE);
#else // CLIPPERUTILS_OFFSET_SCALE
float delta_scaled = delta;
#endif // CLIPPERUTILS_OFFSET_SCALE
ClipperLib::Paths contours;
{
ClipperLib::Path input = Slic3rMultiPoint_to_ClipperPath(expolygon.contour);
#ifdef CLIPPERUTILS_OFFSET_SCALE
scaleClipperPolygon(input);
#endif // CLIPPERUTILS_OFFSET_SCALE
ClipperLib::ClipperOffset co;
if (joinType == jtRound)
#ifdef CLIPPERUTILS_OFFSET_SCALE
co.ArcTolerance = miterLimit * double(CLIPPER_OFFSET_SCALE);
#else // CLIPPERUTILS_OFFSET_SCALE
co.ArcTolerance = miterLimit;
#endif // CLIPPERUTILS_OFFSET_SCALE
else
co.MiterLimit = miterLimit;
co.ShortestEdgeLength = double(std::abs(delta_scaled * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR));
@ -278,17 +298,23 @@ ClipperLib::Paths _offset(const Slic3r::ExPolygon &expolygon, const float delta,
holes.reserve(expolygon.holes.size());
for (Polygons::const_iterator it_hole = expolygon.holes.begin(); it_hole != expolygon.holes.end(); ++ it_hole) {
ClipperLib::Path input = Slic3rMultiPoint_to_ClipperPath_reversed(*it_hole);
#ifdef CLIPPERUTILS_OFFSET_SCALE
scaleClipperPolygon(input);
#endif // CLIPPERUTILS_OFFSET_SCALE
ClipperLib::ClipperOffset co;
if (joinType == jtRound)
#ifdef CLIPPERUTILS_OFFSET_SCALE
co.ArcTolerance = miterLimit * double(CLIPPER_OFFSET_SCALE);
#else // CLIPPERUTILS_OFFSET_SCALE
co.ArcTolerance = miterLimit;
#endif // CLIPPERUTILS_OFFSET_SCALE
else
co.MiterLimit = miterLimit;
co.ShortestEdgeLength = double(std::abs(delta_scaled * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR));
co.AddPath(input, joinType, ClipperLib::etClosedPolygon);
ClipperLib::Paths out;
co.Execute(out, - delta_scaled);
holes.insert(holes.end(), out.begin(), out.end());
append(holes, std::move(out));
}
}
@ -305,7 +331,9 @@ ClipperLib::Paths _offset(const Slic3r::ExPolygon &expolygon, const float delta,
}
// 4) Unscale the output.
#ifdef CLIPPERUTILS_OFFSET_SCALE
unscaleClipperPolygons(output);
#endif // CLIPPERUTILS_OFFSET_SCALE
return output;
}
@ -315,7 +343,11 @@ ClipperLib::Paths _offset(const Slic3r::ExPolygon &expolygon, const float delta,
ClipperLib::Paths _offset(const Slic3r::ExPolygons &expolygons, const float delta,
ClipperLib::JoinType joinType, double miterLimit)
{
const float delta_scaled = delta * float(CLIPPER_OFFSET_SCALE);
#ifdef CLIPPERUTILS_OFFSET_SCALE
float delta_scaled = delta * float(CLIPPER_OFFSET_SCALE);
#else // CLIPPERUTILS_OFFSET_SCALE
float delta_scaled = delta;
#endif // CLIPPERUTILS_OFFSET_SCALE
// Offsetted ExPolygons before they are united.
ClipperLib::Paths contours_cummulative;
contours_cummulative.reserve(expolygons.size());
@ -327,10 +359,16 @@ ClipperLib::Paths _offset(const Slic3r::ExPolygons &expolygons, const float delt
ClipperLib::Paths contours;
{
ClipperLib::Path input = Slic3rMultiPoint_to_ClipperPath(it_expoly->contour);
#ifdef CLIPPERUTILS_OFFSET_SCALE
scaleClipperPolygon(input);
#endif // CLIPPERUTILS_OFFSET_SCALE
ClipperLib::ClipperOffset co;
if (joinType == jtRound)
#ifdef CLIPPERUTILS_OFFSET_SCALE
co.ArcTolerance = miterLimit * double(CLIPPER_OFFSET_SCALE);
#else // CLIPPERUTILS_OFFSET_SCALE
co.ArcTolerance = miterLimit;
#endif // CLIPPERUTILS_OFFSET_SCALE
else
co.MiterLimit = miterLimit;
co.ShortestEdgeLength = double(std::abs(delta_scaled * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR));
@ -351,10 +389,16 @@ ClipperLib::Paths _offset(const Slic3r::ExPolygons &expolygons, const float delt
{
for (Polygons::const_iterator it_hole = it_expoly->holes.begin(); it_hole != it_expoly->holes.end(); ++ it_hole) {
ClipperLib::Path input = Slic3rMultiPoint_to_ClipperPath_reversed(*it_hole);
#ifdef CLIPPERUTILS_OFFSET_SCALE
scaleClipperPolygon(input);
#endif // CLIPPERUTILS_OFFSET_SCALE
ClipperLib::ClipperOffset co;
if (joinType == jtRound)
#ifdef CLIPPERUTILS_OFFSET_SCALE
co.ArcTolerance = miterLimit * double(CLIPPER_OFFSET_SCALE);
#else // CLIPPERUTILS_OFFSET_SCALE
co.ArcTolerance = miterLimit;
#endif // CLIPPERUTILS_OFFSET_SCALE
else
co.MiterLimit = miterLimit;
co.ShortestEdgeLength = double(std::abs(delta_scaled * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR));
@ -413,8 +457,10 @@ ClipperLib::Paths _offset(const Slic3r::ExPolygons &expolygons, const float delt
output = std::move(contours_cummulative);
}
#ifdef CLIPPERUTILS_OFFSET_SCALE
// 4) Unscale the output.
unscaleClipperPolygons(output);
#endif // CLIPPERUTILS_OFFSET_SCALE
return output;
}
@ -425,8 +471,10 @@ _offset2(const Polygons &polygons, const float delta1, const float delta2,
// read input
ClipperLib::Paths input = Slic3rMultiPoints_to_ClipperPaths(polygons);
#ifdef CLIPPERUTILS_OFFSET_SCALE
// scale input
scaleClipperPolygons(input);
#endif // CLIPPERUTILS_OFFSET_SCALE
// prepare ClipperOffset object
ClipperLib::ClipperOffset co;
@ -435,8 +483,13 @@ _offset2(const Polygons &polygons, const float delta1, const float delta2,
} else {
co.MiterLimit = miterLimit;
}
#ifdef CLIPPERUTILS_OFFSET_SCALE
float delta_scaled1 = delta1 * float(CLIPPER_OFFSET_SCALE);
float delta_scaled2 = delta2 * float(CLIPPER_OFFSET_SCALE);
#else // CLIPPERUTILS_OFFSET_SCALE
float delta_scaled1 = delta1;
float delta_scaled2 = delta2;
#endif // CLIPPERUTILS_OFFSET_SCALE
co.ShortestEdgeLength = double(std::max(std::abs(delta_scaled1), std::abs(delta_scaled2)) * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR);
// perform first offset
@ -450,8 +503,10 @@ _offset2(const Polygons &polygons, const float delta1, const float delta2,
ClipperLib::Paths retval;
co.Execute(retval, delta_scaled2);
#ifdef CLIPPERUTILS_OFFSET_SCALE
// unscale output
unscaleClipperPolygons(retval);
#endif // CLIPPERUTILS_OFFSET_SCALE
return retval;
}
@ -789,8 +844,10 @@ void safety_offset(ClipperLib::Paths* paths)
{
CLIPPERUTILS_PROFILE_FUNC();
#ifdef CLIPPERUTILS_OFFSET_SCALE
// scale input
scaleClipperPolygons(*paths);
#endif // CLIPPERUTILS_OFFSET_SCALE
// perform offset (delta = scale 1e-05)
ClipperLib::ClipperOffset co;
@ -816,7 +873,11 @@ void safety_offset(ClipperLib::Paths* paths)
CLIPPERUTILS_PROFILE_BLOCK(safety_offset_Execute);
// offset outside by 10um
ClipperLib::Paths out_this;
#ifdef CLIPPERUTILS_OFFSET_SCALE
co.Execute(out_this, ccw ? 10.f * float(CLIPPER_OFFSET_SCALE) : -10.f * float(CLIPPER_OFFSET_SCALE));
#else // CLIPPERUTILS_OFFSET_SCALE
co.Execute(out_this, ccw ? 10.f : -10.f);
#endif // CLIPPERUTILS_OFFSET_SCALE
if (! ccw) {
// Reverse the resulting contours once again.
for (ClipperLib::Paths::iterator it = out_this.begin(); it != out_this.end(); ++ it)
@ -830,8 +891,10 @@ void safety_offset(ClipperLib::Paths* paths)
}
*paths = std::move(out);
#ifdef CLIPPERUTILS_OFFSET_SCALE
// unscale output
unscaleClipperPolygons(*paths);
#endif // CLIPPERUTILS_OFFSET_SCALE
}
Polygons top_level_islands(const Slic3r::Polygons &polygons)
@ -925,8 +988,10 @@ ClipperLib::Path mittered_offset_path_scaled(const Points &contour, const std::v
// Add a new point to the output, scale by CLIPPER_OFFSET_SCALE and round to ClipperLib::cInt.
auto add_offset_point = [&out](Vec2d pt) {
#ifdef CLIPPERUTILS_OFFSET_SCALE
pt *= double(CLIPPER_OFFSET_SCALE);
pt += Vec2d(0.5 - (pt.x() < 0), 0.5 - (pt.y() < 0));
#endif // CLIPPERUTILS_OFFSET_SCALE
pt += Vec2d(0.5 - (pt.x() < 0), 0.5 - (pt.y() < 0));
out.emplace_back(ClipperLib::cInt(pt.x()), ClipperLib::cInt(pt.y()));
};
@ -1075,8 +1140,10 @@ Polygons variable_offset_inner(const ExPolygon &expoly, const std::vector<std::v
clipper.Execute(ClipperLib::ctDifference, output, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
}
#ifdef CLIPPERUTILS_OFFSET_SCALE
// 4) Unscale the output.
unscaleClipperPolygons(output);
#endif // CLIPPERUTILS_OFFSET_SCALE
return ClipperPaths_to_Slic3rPolygons(output);
}
@ -1119,8 +1186,10 @@ for (const std::vector<float>& ds : deltas)
clipper.Execute(ClipperLib::ctDifference, output, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
}
#ifdef CLIPPERUTILS_OFFSET_SCALE
// 4) Unscale the output.
unscaleClipperPolygons(output);
#endif // CLIPPERUTILS_OFFSET_SCALE
return ClipperPaths_to_Slic3rPolygons(output);
}
@ -1152,7 +1221,9 @@ for (const std::vector<float>& ds : deltas)
#endif /* NDEBUG */
// 3) Subtract holes from the contours.
#ifdef CLIPPERUTILS_OFFSET_SCALE
unscaleClipperPolygons(contours);
#endif // CLIPPERUTILS_OFFSET_SCALE
ExPolygons output;
if (holes.empty()) {
output.reserve(contours.size());
@ -1160,7 +1231,9 @@ for (const std::vector<float>& ds : deltas)
output.emplace_back(ClipperPath_to_Slic3rPolygon(path));
} else {
ClipperLib::Clipper clipper;
#ifdef CLIPPERUTILS_OFFSET_SCALE
unscaleClipperPolygons(holes);
#endif // CLIPPERUTILS_OFFSET_SCALE
clipper.AddPaths(contours, ClipperLib::ptSubject, true);
clipper.AddPaths(holes, ClipperLib::ptClip, true);
ClipperLib::PolyTree polytree;
@ -1200,7 +1273,9 @@ ExPolygons variable_offset_inner_ex(const ExPolygon &expoly, const std::vector<s
#endif /* NDEBUG */
// 3) Subtract holes from the contours.
#ifdef CLIPPERUTILS_OFFSET_SCALE
unscaleClipperPolygons(contours);
#endif // CLIPPERUTILS_OFFSET_SCALE
ExPolygons output;
if (holes.empty()) {
output.reserve(contours.size());
@ -1208,7 +1283,9 @@ ExPolygons variable_offset_inner_ex(const ExPolygon &expoly, const std::vector<s
output.emplace_back(ClipperPath_to_Slic3rPolygon(path));
} else {
ClipperLib::Clipper clipper;
#ifdef CLIPPERUTILS_OFFSET_SCALE
unscaleClipperPolygons(holes);
#endif // CLIPPERUTILS_OFFSET_SCALE
clipper.AddPaths(contours, ClipperLib::ptSubject, true);
clipper.AddPaths(holes, ClipperLib::ptClip, true);
ClipperLib::PolyTree polytree;

View file

@ -12,17 +12,23 @@ using ClipperLib::jtMiter;
using ClipperLib::jtRound;
using ClipperLib::jtSquare;
// Factor to convert from coord_t (which is int32) to an int64 type used by the Clipper library
// for general offsetting (the offset(), offset2(), offset_ex() functions) and for the safety offset,
// which is optionally executed by other functions (union, intersection, diff).
// This scaling (cca 130t) is applied over the usual SCALING_FACTOR.
// By the way, is the scalling for offset needed at all?
// The reason to apply this scaling may be to match the resolution of the double mantissa.
#define CLIPPER_OFFSET_POWER_OF_2 17
// 2^17=131072
#define CLIPPER_OFFSET_SCALE (1 << CLIPPER_OFFSET_POWER_OF_2)
#define CLIPPER_OFFSET_SCALE_ROUNDING_DELTA ((1 << (CLIPPER_OFFSET_POWER_OF_2 - 1)) - 1)
#define CLIPPER_MAX_COORD_UNSCALED (ClipperLib::hiRange / CLIPPER_OFFSET_SCALE)
#define CLIPPERUTILS_UNSAFE_OFFSET
// #define CLIPPERUTILS_OFFSET_SCALE
#ifdef CLIPPERUTILS_OFFSET_SCALE
// Factor to convert from coord_t (which is int32) to an int64 type used by the Clipper library
// for general offsetting (the offset(), offset2(), offset_ex() functions) and for the safety offset,
// which is optionally executed by other functions (union, intersection, diff).
// This scaling (cca 130t) is applied over the usual SCALING_FACTOR.
// By the way, is the scalling for offset needed at all?
// The reason to apply this scaling may be to match the resolution of the double mantissa.
#define CLIPPER_OFFSET_POWER_OF_2 17
// 2^17=131072
#define CLIPPER_OFFSET_SCALE (1 << CLIPPER_OFFSET_POWER_OF_2)
#define CLIPPER_OFFSET_SCALE_ROUNDING_DELTA ((1 << (CLIPPER_OFFSET_POWER_OF_2 - 1)) - 1)
#define CLIPPER_MAX_COORD_UNSCALED (ClipperLib::hiRange / CLIPPER_OFFSET_SCALE)
#endif // CLIPPERUTILS_OFFSET_SCALE
namespace Slic3r {
@ -47,8 +53,11 @@ ClipperLib::Paths _offset(ClipperLib::Path &&input, ClipperLib::EndType endType,
ClipperLib::Paths _offset(ClipperLib::Paths &&input, ClipperLib::EndType endType, const float delta, ClipperLib::JoinType joinType, double miterLimit);
inline Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
{ return ClipperPaths_to_Slic3rPolygons(_offset(Slic3rMultiPoint_to_ClipperPath(polygon), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); }
#ifdef CLIPPERUTILS_UNSAFE_OFFSET
inline Slic3r::Polygons offset(const Slic3r::Polygons &polygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
{ return ClipperPaths_to_Slic3rPolygons(_offset(Slic3rMultiPoints_to_ClipperPaths(polygons), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); }
#endif // CLIPPERUTILS_UNSAFE_OFFSET
// offset Polylines
inline Slic3r::Polygons offset(const Slic3r::Polyline &polyline, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtSquare, double miterLimit = 3)
@ -65,13 +74,18 @@ inline Slic3r::Polygons offset(const Slic3r::ExPolygons &expolygons, const float
{ return ClipperPaths_to_Slic3rPolygons(_offset(expolygons, delta, joinType, miterLimit)); }
inline Slic3r::ExPolygons offset_ex(const Slic3r::Polygon &polygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
{ return ClipperPaths_to_Slic3rExPolygons(_offset(Slic3rMultiPoint_to_ClipperPath(polygon), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); }
#ifdef CLIPPERUTILS_UNSAFE_OFFSET
inline Slic3r::ExPolygons offset_ex(const Slic3r::Polygons &polygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
{ return ClipperPaths_to_Slic3rExPolygons(_offset(Slic3rMultiPoints_to_ClipperPaths(polygons), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); }
#endif // CLIPPERUTILS_UNSAFE_OFFSET
inline Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
{ return ClipperPaths_to_Slic3rExPolygons(_offset(expolygon, delta, joinType, miterLimit)); }
inline Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygons &expolygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
{ return ClipperPaths_to_Slic3rExPolygons(_offset(expolygons, delta, joinType, miterLimit)); }
#ifdef CLIPPERUTILS_UNSAFE_OFFSET
ClipperLib::Paths _offset2(const Slic3r::Polygons &polygons, const float delta1,
const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
double miterLimit = 3);
@ -81,6 +95,8 @@ Slic3r::Polygons offset2(const Slic3r::Polygons &polygons, const float delta1,
Slic3r::ExPolygons offset2_ex(const Slic3r::Polygons &polygons, const float delta1,
const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
double miterLimit = 3);
#endif // CLIPPERUTILS_UNSAFE_OFFSET
Slic3r::ExPolygons offset2_ex(const Slic3r::ExPolygons &expolygons, const float delta1,
const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
double miterLimit = 3);
@ -319,6 +335,7 @@ void safety_offset(ClipperLib::Paths* paths);
Polygons top_level_islands(const Slic3r::Polygons &polygons);
ClipperLib::Path mittered_offset_path_scaled(const Points &contour, const std::vector<float> &deltas, double miter_limit);
Polygons variable_offset_inner(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit = 2.);
Polygons variable_offset_outer(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit = 2.);
ExPolygons variable_offset_outer_ex(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit = 2.);

View file

@ -471,8 +471,8 @@ bool ConfigBase::set_deserialize_nothrow(const t_config_option_key &opt_key_src,
{
t_config_option_key opt_key = opt_key_src;
std::string value = value_src;
// Both opt_key and value may be modified by _handle_legacy().
// If the opt_key is no more valid in this version of Slic3r, opt_key is cleared by _handle_legacy().
// Both opt_key and value may be modified by handle_legacy().
// If the opt_key is no more valid in this version of Slic3r, opt_key is cleared by handle_legacy().
this->handle_legacy(opt_key, value);
if (opt_key.empty())
// Ignore the option.

View file

@ -1967,8 +1967,9 @@ public:
int opt_int(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionInts*>(this->option(opt_key))->get_at(idx); }
// In ConfigManipulation::toggle_print_fff_options, it is called on option with type ConfigOptionEnumGeneric* and also ConfigOptionEnum*.
// Thus the virtual method getInt() is used to retrieve the enum value.
template<typename ENUM>
ENUM opt_enum(const t_config_option_key &opt_key) const { return this->option<ConfigOptionEnum<ENUM>>(opt_key)->value; }
ENUM opt_enum(const t_config_option_key &opt_key) const { return static_cast<ENUM>(this->option(opt_key)->getInt()); }
bool opt_bool(const t_config_option_key &opt_key) const { return this->option<ConfigOptionBool>(opt_key)->value != 0; }
bool opt_bool(const t_config_option_key &opt_key, unsigned int idx) const { return this->option<ConfigOptionBools>(opt_key)->get_at(idx) != 0; }

View file

@ -217,6 +217,28 @@ inline Polygons to_polygons(const ExPolygons &src)
return polygons;
}
inline ConstPolygonPtrs to_polygon_ptrs(const ExPolygon &src)
{
ConstPolygonPtrs polygons;
polygons.reserve(src.holes.size() + 1);
polygons.emplace_back(&src.contour);
for (const Polygon &hole : src.holes)
polygons.emplace_back(&hole);
return polygons;
}
inline ConstPolygonPtrs to_polygon_ptrs(const ExPolygons &src)
{
ConstPolygonPtrs polygons;
polygons.reserve(number_polygons(src));
for (const ExPolygon &expoly : src) {
polygons.emplace_back(&expoly.contour);
for (const Polygon &hole : expoly.holes)
polygons.emplace_back(&hole);
}
return polygons;
}
inline Polygons to_polygons(ExPolygon &&src)
{
Polygons polygons;

View file

@ -24,11 +24,11 @@ void FillConcentric::_fill_surface_single(
this->spacing = unscale<double>(distance);
}
Polygons loops = to_polygons(std::move(expolygon));
Polygons last = loops;
Polygons loops = to_polygons(expolygon);
ExPolygons last { std::move(expolygon) };
while (! last.empty()) {
last = offset2(last, -(distance + min_spacing/2), +min_spacing/2);
append(loops, last);
last = offset2_ex(last, -(distance + min_spacing/2), +min_spacing/2);
append(loops, to_polygons(last));
}
// generate paths from the outermost to the innermost, to avoid

View file

@ -58,7 +58,7 @@ void FillLine::_fill_surface_single(
pts.push_back(it->a);
pts.push_back(it->b);
}
Polylines polylines = intersection_pl(polylines_src, offset(to_polygons(expolygon), scale_(0.02)), false);
Polylines polylines = intersection_pl(polylines_src, offset(expolygon, scale_(0.02)), false);
// FIXME Vojtech: This is only performed for horizontal lines, not for the vertical lines!
const float INFILL_OVERLAP_OVER_SPACING = 0.3f;

View file

@ -238,13 +238,14 @@ Flow support_material_flow(const PrintObject *object, float layer_height)
Flow support_material_1st_layer_flow(const PrintObject *object, float layer_height)
{
const auto &width = (object->print()->config().first_layer_extrusion_width.value > 0) ? object->print()->config().first_layer_extrusion_width : object->config().support_material_extrusion_width;
const PrintConfig &print_config = object->print()->config();
const auto &width = (print_config.first_layer_extrusion_width.value > 0) ? print_config.first_layer_extrusion_width : object->config().support_material_extrusion_width;
return Flow::new_from_config_width(
frSupportMaterial,
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
(width.value > 0) ? width : object->config().extrusion_width,
float(object->print()->config().nozzle_diameter.get_at(object->config().support_material_extruder-1)),
(layer_height > 0.f) ? layer_height : float(object->config().first_layer_height.get_abs_value(object->config().layer_height.value)));
float(print_config.nozzle_diameter.get_at(object->config().support_material_extruder-1)),
(layer_height > 0.f) ? layer_height : float(print_config.first_layer_height.get_abs_value(object->config().layer_height.value)));
}
Flow support_material_interface_flow(const PrintObject *object, float layer_height)

View file

@ -1111,7 +1111,7 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
// Write some terse information on the slicing parameters.
const PrintObject *first_object = print.objects().front();
const double layer_height = first_object->config().layer_height.value;
const double first_layer_height = first_object->config().first_layer_height.get_abs_value(layer_height);
const double first_layer_height = print.config().first_layer_height.get_abs_value(layer_height);
for (const PrintRegion* region : print.regions()) {
_write_format(file, "; external perimeters extrusion width = %.2fmm\n", region->flow(*first_object, frExternalPerimeter, layer_height).width());
_write_format(file, "; perimeters extrusion width = %.2fmm\n", region->flow(*first_object, frPerimeter, layer_height).width());
@ -1778,6 +1778,10 @@ namespace ProcessLayer
else {
gcode += gcodegen.placeholder_parser_process("color_change_gcode", config.color_change_gcode, current_extruder_id);
gcode += "\n";
//FIXME Tell G-code writer that M600 filled the extruder, thus the G-code writer shall reset the extruder to unretracted state after
// return from M600. Thus the G-code generated by the following line is ignored.
// see GH issue #6362
gcodegen.writer().unretract();
}
}
else {

View file

@ -1087,11 +1087,13 @@ bool
MedialAxis::validate_edge(const VD::edge_type* edge)
{
// prevent overflows and detect almost-infinite edges
#ifndef CLIPPERLIB_INT32
if (std::abs(edge->vertex0()->x()) > double(CLIPPER_MAX_COORD_UNSCALED) ||
std::abs(edge->vertex0()->y()) > double(CLIPPER_MAX_COORD_UNSCALED) ||
std::abs(edge->vertex1()->x()) > double(CLIPPER_MAX_COORD_UNSCALED) ||
std::abs(edge->vertex1()->y()) > double(CLIPPER_MAX_COORD_UNSCALED))
return false;
#endif // CLIPPERLIB_INT32
// construct the line representing this edge of the Voronoi diagram
const Line line(

View file

@ -216,7 +216,7 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
break;
}
// Grown by 3mm.
Polygons polys = offset(to_polygons(bridges[i].expolygon), margin, EXTERNAL_SURFACES_OFFSET_PARAMETERS);
Polygons polys = offset(bridges[i].expolygon, margin, EXTERNAL_SURFACES_OFFSET_PARAMETERS);
if (idx_island == -1) {
BOOST_LOG_TRIVIAL(trace) << "Bridge did not fall into the source region!";
} else {

View file

@ -11,7 +11,9 @@
namespace Slic3r {
class Polygon;
typedef std::vector<Polygon> Polygons;
using Polygons = std::vector<Polygon>;
using PolygonPtrs = std::vector<Polygon*>;
using ConstPolygonPtrs = std::vector<const Polygon*>;
class Polygon : public MultiPoint
{

View file

@ -296,6 +296,13 @@ void Preset::normalize(DynamicPrintConfig &config)
if (auto *gap_fill_enabled = config.option<ConfigOptionBool>("gap_fill_enabled", false); gap_fill_enabled)
gap_fill_enabled->value = false;
}
if (auto *first_layer_height = config.option<ConfigOptionFloatOrPercent>("first_layer_height", false); first_layer_height && first_layer_height->percent)
if (const auto *layer_height = config.option<ConfigOptionFloat>("layer_height", false); layer_height) {
// Legacy conversion - first_layer_height moved from PrintObject setting to a Print setting, thus we are getting rid of the dependency
// of first_layer_height on PrintObject specific layer_height. Covert the first layer heigth to an absolute value.
first_layer_height->value = first_layer_height->get_abs_value(layer_height->value);
first_layer_height->percent = false;
}
}
std::string Preset::remove_invalid_keys(DynamicPrintConfig &config, const DynamicPrintConfig &default_config)
@ -427,7 +434,7 @@ const std::vector<std::string>& Preset::print_options()
"bridge_acceleration", "first_layer_acceleration", "default_acceleration", "skirts", "skirt_distance", "skirt_height", "draft_shield",
"min_skirt_length", "brim_width", "brim_offset", "brim_type", "support_material", "support_material_auto", "support_material_threshold", "support_material_enforce_layers",
"raft_layers", "raft_first_layer_density", "raft_first_layer_expansion", "raft_contact_distance", "raft_expansion",
"support_material_pattern", "support_material_with_sheath", "support_material_spacing", "support_material_style",
"support_material_pattern", "support_material_with_sheath", "support_material_spacing", "support_material_closing_radius", "support_material_style",
"support_material_synchronize_layers", "support_material_angle", "support_material_interface_layers", "support_material_bottom_interface_layers",
"support_material_interface_pattern", "support_material_interface_spacing", "support_material_interface_contact_loops",
"support_material_contact_distance", "support_material_bottom_contact_distance",

View file

@ -995,10 +995,8 @@ void PrintConfigDef::init_fff_params()
def->label = L("First layer height");
def->category = L("Layers and Perimeters");
def->tooltip = L("When printing with very low layer heights, you might still want to print a thicker "
"bottom layer to improve adhesion and tolerance for non perfect build plates. "
"This can be expressed as an absolute value or as a percentage (for example: 150%) "
"over the default layer height.");
def->sidetext = L("mm or %");
"bottom layer to improve adhesion and tolerance for non perfect build plates.");
def->sidetext = L("mm");
def->ratio_over = "layer_height";
def->set_default_value(new ConfigOptionFloatOrPercent(0.35, false));
@ -2366,6 +2364,16 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionInt(-1));
def = this->add("support_material_closing_radius", coFloat);
def->label = L("Closing radius");
def->category = L("Support material");
def->tooltip = L("For snug supports, the support regions will be merged using morphological closing operation."
" Gaps smaller than the closing radius will be filled in.");
def->sidetext = L("mm");
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(2));
def = this->add("support_material_interface_spacing", coFloat);
def->label = L("Interface pattern spacing");
def->category = L("Support material");
@ -3618,7 +3626,7 @@ std::string FullPrintConfig::validate()
return "--layer-height must be a multiple of print resolution";
// --first-layer-height
if (this->get_abs_value("first_layer_height") <= 0)
if (first_layer_height.value <= 0)
return "Invalid value for --first-layer-height";
// --filament-diameter

View file

@ -496,7 +496,6 @@ public:
ConfigOptionBool dont_support_bridges;
ConfigOptionFloat elefant_foot_compensation;
ConfigOptionFloatOrPercent extrusion_width;
ConfigOptionFloatOrPercent first_layer_height;
ConfigOptionBool infill_only_where_needed;
// Force the generation of solid shells between adjacent materials/volumes.
ConfigOptionBool interface_shells;
@ -530,6 +529,8 @@ public:
ConfigOptionFloatOrPercent support_material_interface_speed;
ConfigOptionEnum<SupportMaterialPattern> support_material_pattern;
ConfigOptionEnum<SupportMaterialInterfacePattern> support_material_interface_pattern;
// Morphological closing of support areas. Only used for "sung" supports.
ConfigOptionFloat support_material_closing_radius;
// Spacing between support material lines (the hatching distance).
ConfigOptionFloat support_material_spacing;
ConfigOptionFloat support_material_speed;
@ -553,7 +554,6 @@ protected:
OPT_PTR(dont_support_bridges);
OPT_PTR(elefant_foot_compensation);
OPT_PTR(extrusion_width);
OPT_PTR(first_layer_height);
OPT_PTR(infill_only_where_needed);
OPT_PTR(interface_shells);
OPT_PTR(layer_height);
@ -579,6 +579,7 @@ protected:
OPT_PTR(support_material_interface_extruder);
OPT_PTR(support_material_interface_layers);
OPT_PTR(support_material_bottom_interface_layers);
OPT_PTR(support_material_closing_radius);
OPT_PTR(support_material_interface_spacing);
OPT_PTR(support_material_interface_speed);
OPT_PTR(support_material_pattern);
@ -947,6 +948,7 @@ public:
ConfigOptionFloat first_layer_acceleration;
ConfigOptionInts first_layer_bed_temperature;
ConfigOptionFloatOrPercent first_layer_extrusion_width;
ConfigOptionFloatOrPercent first_layer_height;
ConfigOptionFloatOrPercent first_layer_speed;
ConfigOptionInts first_layer_temperature;
ConfigOptionInts full_fan_speed_layer;
@ -1022,6 +1024,7 @@ protected:
OPT_PTR(first_layer_acceleration);
OPT_PTR(first_layer_bed_temperature);
OPT_PTR(first_layer_extrusion_width);
OPT_PTR(first_layer_height);
OPT_PTR(first_layer_speed);
OPT_PTR(first_layer_temperature);
OPT_PTR(full_fan_speed_layer);

View file

@ -591,6 +591,7 @@ bool PrintObject::invalidate_state_by_config_options(
|| opt_key == "support_material_style"
|| opt_key == "support_material_xy_spacing"
|| opt_key == "support_material_spacing"
|| opt_key == "support_material_closing_radius"
|| opt_key == "support_material_synchronize_layers"
|| opt_key == "support_material_threshold"
|| opt_key == "support_material_with_sheath"

View file

@ -64,9 +64,9 @@ SlicingParameters SlicingParameters::create_from_config(
coordf_t object_height,
const std::vector<unsigned int> &object_extruders)
{
coordf_t first_layer_height = (object_config.first_layer_height.value <= 0) ?
coordf_t first_layer_height = (print_config.first_layer_height.value <= 0) ?
object_config.layer_height.value :
object_config.first_layer_height.get_abs_value(object_config.layer_height.value);
print_config.first_layer_height.get_abs_value(object_config.layer_height.value);
// If object_config.support_material_extruder == 0 resp. object_config.support_material_interface_extruder == 0,
// print_config.nozzle_diameter.get_at(size_t(-1)) returns the 0th nozzle diameter,
// which is consistent with the requirement that if support_material_extruder == 0 resp. support_material_interface_extruder == 0,

View file

@ -672,6 +672,7 @@ struct SupportGridParams {
grid_resolution(object_config.support_material_spacing.value + support_material_flow.spacing()),
support_angle(Geometry::deg2rad(object_config.support_material_angle.value)),
extrusion_width(support_material_flow.spacing()),
support_material_closing_radius(object_config.support_material_closing_radius.value),
expansion_to_slice(coord_t(support_material_flow.scaled_spacing() / 2 + 5)),
expansion_to_propagate(-3) {}
@ -679,6 +680,7 @@ struct SupportGridParams {
double grid_resolution;
double support_angle;
double extrusion_width;
double support_material_closing_radius;
coord_t expansion_to_slice;
coord_t expansion_to_propagate;
};
@ -694,7 +696,9 @@ public:
const SupportGridParams &params) :
m_style(params.style),
m_support_polygons(support_polygons), m_trimming_polygons(trimming_polygons),
m_support_spacing(params.grid_resolution), m_support_angle(params.support_angle)
m_support_spacing(params.grid_resolution), m_support_angle(params.support_angle),
m_extrusion_width(params.extrusion_width),
m_support_material_closing_radius(params.support_material_closing_radius)
{
switch (m_style) {
case smsGrid:
@ -878,9 +882,10 @@ public:
return out;
}
case smsSnug:
// Just close the gaps.
float thr = scaled<float>(0.5);
return smooth_outward(offset(offset_ex(*m_support_polygons, thr), - thr), thr);
// Merge the support polygons by applying morphological closing and inwards smoothing.
auto closing_distance = scaled<float>(m_support_material_closing_radius);
auto smoothing_distance = scaled<float>(m_extrusion_width);
return smooth_outward(offset(offset_ex(*m_support_polygons, closing_distance), - closing_distance), smoothing_distance);
}
assert(false);
return Polygons();
@ -1128,6 +1133,9 @@ private:
coordf_t m_support_angle;
// X spacing of the support lines parallel with the Y axis.
coordf_t m_support_spacing;
coordf_t m_extrusion_width;
// For snug supports: Morphological closing of support areas.
coordf_t m_support_material_closing_radius;
#ifdef SUPPORT_USE_AGG_RASTERIZER
Vec2i m_grid_size;
@ -3178,7 +3186,7 @@ struct MyLayerExtruded
MyLayerExtruded& operator=(MyLayerExtruded &&rhs) {
this->layer = rhs.layer;
this->extrusions = std::move(rhs.extrusions);
this->m_polygons_to_extrude = std::move(m_polygons_to_extrude);
this->m_polygons_to_extrude = std::move(rhs.m_polygons_to_extrude);
rhs.layer = nullptr;
return *this;
}

View file

@ -57,6 +57,8 @@
#define ENABLE_GCODE_WINDOW (1 && ENABLE_2_4_0_ALPHA0)
// Enable exporting lines M73 for remaining time to next printer stop to gcode
#define ENABLE_EXTENDED_M73_LINES (1 && ENABLE_VALIDATE_CUSTOM_GCODE)
// Enable a modified version of automatic downscale on load of objects too big
#define ENABLE_MODIFIED_DOWNSCALE_ON_LOAD_OBJECTS_TOO_BIG (1 && ENABLE_2_4_0_ALPHA0)
#endif // _prusaslicer_technologies_h_

View file

@ -511,20 +511,22 @@ void TriangleMesh::merge(const TriangleMesh &mesh)
//FIXME This could be extremely slow! Use it for tiny meshes only!
ExPolygons TriangleMesh::horizontal_projection() const
{
Polygons pp;
pp.reserve(this->stl.stats.number_of_facets);
ClipperLib::Paths paths;
Polygon p;
p.points.assign(3, Point());
auto delta = scaled<float>(0.01);
std::vector<float> deltas { delta, delta, delta };
paths.reserve(this->stl.stats.number_of_facets);
for (const stl_facet &facet : this->stl.facet_start) {
Polygon p;
p.points.resize(3);
p.points[0] = Point::new_scale(facet.vertex[0](0), facet.vertex[0](1));
p.points[1] = Point::new_scale(facet.vertex[1](0), facet.vertex[1](1));
p.points[2] = Point::new_scale(facet.vertex[2](0), facet.vertex[2](1));
p.make_counter_clockwise(); // do this after scaling, as winding order might change while doing that
pp.emplace_back(p);
p.make_counter_clockwise();
paths.emplace_back(mittered_offset_path_scaled(p.points, deltas, 3.));
}
// the offset factor was tuned using groovemount.stl
return union_ex(offset(pp, scale_(0.01)), true);
return ClipperPaths_to_Slic3rExPolygons(paths);
}
// 2D convex hull of a 3D mesh projected into the Z=0 plane.
@ -1797,7 +1799,7 @@ void TriangleMeshSlicer::make_expolygons(const Polygons &loops, const float clos
// append to the supplied collection
if (safety_offset > 0)
expolygons_append(*slices, offset2_ex(union_(loops, false), +safety_offset, -safety_offset));
expolygons_append(*slices, offset2_ex(union_ex(loops, false), +safety_offset, -safety_offset));
else
expolygons_append(*slices, union_ex(loops, false));
}