Merge branch 'vb_clipper_optimization'
This commit is contained in:
commit
eb66111eda
34 changed files with 1007 additions and 1080 deletions
|
@ -759,48 +759,6 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClipperBase::AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed)
|
|
||||||
{
|
|
||||||
CLIPPERLIB_PROFILE_FUNC();
|
|
||||||
std::vector<int> num_edges(ppg.size(), 0);
|
|
||||||
int num_edges_total = 0;
|
|
||||||
for (size_t i = 0; i < ppg.size(); ++ i) {
|
|
||||||
const Path &pg = ppg[i];
|
|
||||||
// Remove duplicate end point from a closed input path.
|
|
||||||
// Remove duplicate points from the end of the input path.
|
|
||||||
int highI = (int)pg.size() -1;
|
|
||||||
if (Closed)
|
|
||||||
while (highI > 0 && (pg[highI] == pg[0]))
|
|
||||||
--highI;
|
|
||||||
while (highI > 0 && (pg[highI] == pg[highI -1]))
|
|
||||||
--highI;
|
|
||||||
if ((Closed && highI < 2) || (!Closed && highI < 1))
|
|
||||||
highI = -1;
|
|
||||||
num_edges[i] = highI + 1;
|
|
||||||
num_edges_total += highI + 1;
|
|
||||||
}
|
|
||||||
if (num_edges_total == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Allocate a new edge array.
|
|
||||||
std::vector<TEdge> edges(num_edges_total);
|
|
||||||
// Fill in the edge array.
|
|
||||||
bool result = false;
|
|
||||||
TEdge *p_edge = edges.data();
|
|
||||||
for (Paths::size_type i = 0; i < ppg.size(); ++i)
|
|
||||||
if (num_edges[i]) {
|
|
||||||
bool res = AddPathInternal(ppg[i], num_edges[i] - 1, PolyTyp, Closed, p_edge);
|
|
||||||
if (res) {
|
|
||||||
p_edge += num_edges[i];
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (result)
|
|
||||||
// At least some edges were generated. Remember the edge array.
|
|
||||||
m_edges.emplace_back(std::move(edges));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ClipperBase::AddPathInternal(const Path &pg, int highI, PolyType PolyTyp, bool Closed, TEdge* edges)
|
bool ClipperBase::AddPathInternal(const Path &pg, int highI, PolyType PolyTyp, bool Closed, TEdge* edges)
|
||||||
{
|
{
|
||||||
CLIPPERLIB_PROFILE_FUNC();
|
CLIPPERLIB_PROFILE_FUNC();
|
||||||
|
@ -1103,7 +1061,7 @@ bool Clipper::Execute(ClipType clipType, Paths &solution,
|
||||||
CLIPPERLIB_PROFILE_FUNC();
|
CLIPPERLIB_PROFILE_FUNC();
|
||||||
if (m_HasOpenPaths)
|
if (m_HasOpenPaths)
|
||||||
throw clipperException("Error: PolyTree struct is needed for open path clipping.");
|
throw clipperException("Error: PolyTree struct is needed for open path clipping.");
|
||||||
solution.resize(0);
|
solution.clear();
|
||||||
m_SubjFillType = subjFillType;
|
m_SubjFillType = subjFillType;
|
||||||
m_ClipFillType = clipFillType;
|
m_ClipFillType = clipFillType;
|
||||||
m_ClipType = clipType;
|
m_ClipType = clipType;
|
||||||
|
@ -3426,13 +3384,6 @@ void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
void ClipperOffset::AddPaths(const Paths& paths, JoinType joinType, EndType endType)
|
|
||||||
{
|
|
||||||
for (const Path &path : paths)
|
|
||||||
AddPath(path, joinType, endType);
|
|
||||||
}
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void ClipperOffset::FixOrientations()
|
void ClipperOffset::FixOrientations()
|
||||||
{
|
{
|
||||||
//fixup orientations of all closed paths if the orientation of the
|
//fixup orientations of all closed paths if the orientation of the
|
||||||
|
@ -3875,28 +3826,16 @@ void ReversePaths(Paths& p)
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType)
|
Paths SimplifyPolygon(const Path &in_poly, PolyFillType fillType)
|
||||||
{
|
{
|
||||||
Clipper c;
|
Clipper c;
|
||||||
c.StrictlySimple(true);
|
c.StrictlySimple(true);
|
||||||
c.AddPath(in_poly, ptSubject, true);
|
c.AddPath(in_poly, ptSubject, true);
|
||||||
c.Execute(ctUnion, out_polys, fillType, fillType);
|
Paths out;
|
||||||
|
c.Execute(ctUnion, out, fillType, fillType);
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType)
|
|
||||||
{
|
|
||||||
Clipper c;
|
|
||||||
c.StrictlySimple(true);
|
|
||||||
c.AddPaths(in_polys, ptSubject, true);
|
|
||||||
c.Execute(ctUnion, out_polys, fillType, fillType);
|
|
||||||
}
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void SimplifyPolygons(Paths &polys, PolyFillType fillType)
|
|
||||||
{
|
|
||||||
SimplifyPolygons(polys, polys, fillType);
|
|
||||||
}
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
inline double DistanceSqrd(const IntPoint& pt1, const IntPoint& pt2)
|
inline double DistanceSqrd(const IntPoint& pt1, const IntPoint& pt2)
|
||||||
|
|
|
@ -191,9 +191,7 @@ double Area(const Path &poly);
|
||||||
inline bool Orientation(const Path &poly) { return Area(poly) >= 0; }
|
inline bool Orientation(const Path &poly) { return Area(poly) >= 0; }
|
||||||
int PointInPolygon(const IntPoint &pt, const Path &path);
|
int PointInPolygon(const IntPoint &pt, const Path &path);
|
||||||
|
|
||||||
void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
|
Paths SimplifyPolygon(const Path &in_poly, PolyFillType fillType = pftEvenOdd);
|
||||||
void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
|
|
||||||
void SimplifyPolygons(Paths &polys, PolyFillType fillType = pftEvenOdd);
|
|
||||||
|
|
||||||
void CleanPolygon(const Path& in_poly, Path& out_poly, double distance = 1.415);
|
void CleanPolygon(const Path& in_poly, Path& out_poly, double distance = 1.415);
|
||||||
void CleanPolygon(Path& poly, double distance = 1.415);
|
void CleanPolygon(Path& poly, double distance = 1.415);
|
||||||
|
@ -300,7 +298,58 @@ public:
|
||||||
m_HasOpenPaths(false) {}
|
m_HasOpenPaths(false) {}
|
||||||
~ClipperBase() { Clear(); }
|
~ClipperBase() { Clear(); }
|
||||||
bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed);
|
bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed);
|
||||||
bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed);
|
|
||||||
|
template<typename PathsProvider>
|
||||||
|
bool AddPaths(PathsProvider &&paths_provider, PolyType PolyTyp, bool Closed)
|
||||||
|
{
|
||||||
|
size_t num_paths = paths_provider.size();
|
||||||
|
if (num_paths == 0)
|
||||||
|
return false;
|
||||||
|
if (num_paths == 1)
|
||||||
|
return AddPath(*paths_provider.begin(), PolyTyp, Closed);
|
||||||
|
|
||||||
|
std::vector<int> num_edges(num_paths, 0);
|
||||||
|
int num_edges_total = 0;
|
||||||
|
size_t i = 0;
|
||||||
|
for (const Path &pg : paths_provider) {
|
||||||
|
// Remove duplicate end point from a closed input path.
|
||||||
|
// Remove duplicate points from the end of the input path.
|
||||||
|
int highI = (int)pg.size() -1;
|
||||||
|
if (Closed)
|
||||||
|
while (highI > 0 && (pg[highI] == pg[0]))
|
||||||
|
--highI;
|
||||||
|
while (highI > 0 && (pg[highI] == pg[highI -1]))
|
||||||
|
--highI;
|
||||||
|
if ((Closed && highI < 2) || (!Closed && highI < 1))
|
||||||
|
highI = -1;
|
||||||
|
num_edges[i ++] = highI + 1;
|
||||||
|
num_edges_total += highI + 1;
|
||||||
|
}
|
||||||
|
if (num_edges_total == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Allocate a new edge array.
|
||||||
|
std::vector<TEdge> edges(num_edges_total);
|
||||||
|
// Fill in the edge array.
|
||||||
|
bool result = false;
|
||||||
|
TEdge *p_edge = edges.data();
|
||||||
|
i = 0;
|
||||||
|
for (const Path &pg : paths_provider) {
|
||||||
|
if (num_edges[i]) {
|
||||||
|
bool res = AddPathInternal(pg, num_edges[i] - 1, PolyTyp, Closed, p_edge);
|
||||||
|
if (res) {
|
||||||
|
p_edge += num_edges[i];
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++ i;
|
||||||
|
}
|
||||||
|
if (result)
|
||||||
|
// At least some edges were generated. Remember the edge array.
|
||||||
|
m_edges.emplace_back(std::move(edges));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
IntRect GetBounds();
|
IntRect GetBounds();
|
||||||
// By default, when three or more vertices are collinear in input polygons (subject or clip), the Clipper object removes the 'inner' vertices before clipping.
|
// By default, when three or more vertices are collinear in input polygons (subject or clip), the Clipper object removes the 'inner' vertices before clipping.
|
||||||
|
@ -461,7 +510,11 @@ public:
|
||||||
MiterLimit(miterLimit), ArcTolerance(roundPrecision), ShortestEdgeLength(shortestEdgeLength), m_lowest(-1, 0) {}
|
MiterLimit(miterLimit), ArcTolerance(roundPrecision), ShortestEdgeLength(shortestEdgeLength), m_lowest(-1, 0) {}
|
||||||
~ClipperOffset() { Clear(); }
|
~ClipperOffset() { Clear(); }
|
||||||
void AddPath(const Path& path, JoinType joinType, EndType endType);
|
void AddPath(const Path& path, JoinType joinType, EndType endType);
|
||||||
void AddPaths(const Paths& paths, JoinType joinType, EndType endType);
|
template<typename PathsProvider>
|
||||||
|
void AddPaths(PathsProvider &&paths, JoinType joinType, EndType endType) {
|
||||||
|
for (const Path &path : paths)
|
||||||
|
AddPath(path, joinType, endType);
|
||||||
|
}
|
||||||
void Execute(Paths& solution, double delta);
|
void Execute(Paths& solution, double delta);
|
||||||
void Execute(PolyTree& solution, double delta);
|
void Execute(PolyTree& solution, double delta);
|
||||||
void Clear();
|
void Clear();
|
||||||
|
@ -498,6 +551,16 @@ class clipperException : public std::exception
|
||||||
};
|
};
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<typename PathsProvider>
|
||||||
|
inline Paths SimplifyPolygons(PathsProvider &&in_polys, PolyFillType fillType = pftEvenOdd) {
|
||||||
|
Clipper c;
|
||||||
|
c.StrictlySimple(true);
|
||||||
|
c.AddPaths(std::forward<PathsProvider>(in_polys), ptSubject, true);
|
||||||
|
Paths out;
|
||||||
|
c.Execute(ctUnion, out, fillType, fillType);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
} //ClipperLib namespace
|
} //ClipperLib namespace
|
||||||
|
|
||||||
#ifdef CLIPPERLIB_NAMESPACE_PREFIX
|
#ifdef CLIPPERLIB_NAMESPACE_PREFIX
|
||||||
|
|
|
@ -227,29 +227,33 @@ void ExPolygon::get_trapezoids(ExPolygon clone, Polygons* polygons, double angle
|
||||||
// This algorithm may return more trapezoids than necessary
|
// This algorithm may return more trapezoids than necessary
|
||||||
// (i.e. it may break a single trapezoid in several because
|
// (i.e. it may break a single trapezoid in several because
|
||||||
// other parts of the object have x coordinates in the middle)
|
// other parts of the object have x coordinates in the middle)
|
||||||
static void get_trapezoids2(const ExPolygon &expoly, Polygons* polygons)
|
static void get_trapezoids2(const ExPolygon& expoly, Polygons* polygons)
|
||||||
{
|
{
|
||||||
Polygons src_polygons = to_polygons(expoly);
|
Polygons src_polygons = to_polygons(expoly);
|
||||||
// get all points of this ExPolygon
|
// get all points of this ExPolygon
|
||||||
const Points pp = to_points(src_polygons);
|
const Points pp = to_points(src_polygons);
|
||||||
|
|
||||||
// build our bounding box
|
// build our bounding box
|
||||||
BoundingBox bb(pp);
|
BoundingBox bb(pp);
|
||||||
|
|
||||||
// get all x coordinates
|
// get all x coordinates
|
||||||
std::vector<coord_t> xx;
|
std::vector<coord_t> xx;
|
||||||
xx.reserve(pp.size());
|
xx.reserve(pp.size());
|
||||||
for (Points::const_iterator p = pp.begin(); p != pp.end(); ++p)
|
for (Points::const_iterator p = pp.begin(); p != pp.end(); ++p)
|
||||||
xx.push_back(p->x());
|
xx.push_back(p->x());
|
||||||
std::sort(xx.begin(), xx.end());
|
std::sort(xx.begin(), xx.end());
|
||||||
|
|
||||||
// find trapezoids by looping from first to next-to-last coordinate
|
// find trapezoids by looping from first to next-to-last coordinate
|
||||||
|
Polygons rectangle;
|
||||||
|
rectangle.emplace_back(Polygon());
|
||||||
for (std::vector<coord_t>::const_iterator x = xx.begin(); x != xx.end()-1; ++x) {
|
for (std::vector<coord_t>::const_iterator x = xx.begin(); x != xx.end()-1; ++x) {
|
||||||
coord_t next_x = *(x + 1);
|
coord_t next_x = *(x + 1);
|
||||||
if (*x != next_x)
|
if (*x != next_x) {
|
||||||
// intersect with rectangle
|
// intersect with rectangle
|
||||||
// append results to return value
|
// append results to return value
|
||||||
polygons_append(*polygons, intersection({ { { *x, bb.min.y() }, { next_x, bb.min.y() }, { next_x, bb.max.y() }, { *x, bb.max.y() } } }, src_polygons));
|
rectangle.front() = { { *x, bb.min.y() }, { next_x, bb.min.y() }, { next_x, bb.max.y() }, { *x, bb.max.y() } };
|
||||||
|
polygons_append(*polygons, intersection(rectangle, src_polygons));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,7 +306,7 @@ Polygons BridgeDetector::coverage(double angle) const
|
||||||
covered = union_(covered);
|
covered = union_(covered);
|
||||||
// Intersect trapezoids with actual bridge area to remove extra margins and append it to result.
|
// Intersect trapezoids with actual bridge area to remove extra margins and append it to result.
|
||||||
polygons_rotate(covered, -(PI/2.0 - angle));
|
polygons_rotate(covered, -(PI/2.0 - angle));
|
||||||
covered = intersection(covered, to_polygons(this->expolygons));
|
covered = intersection(this->expolygons, covered);
|
||||||
#if 0
|
#if 0
|
||||||
{
|
{
|
||||||
my @lines = map @{$_->lines}, @$trapezoids;
|
my @lines = map @{$_->lines}, @$trapezoids;
|
||||||
|
|
|
@ -139,7 +139,7 @@ static ExPolygons top_level_outer_brim_area(const Print &print, const ConstPrint
|
||||||
Polygons no_brim_area_object;
|
Polygons no_brim_area_object;
|
||||||
for (const ExPolygon &ex_poly : object->layers().front()->lslices) {
|
for (const ExPolygon &ex_poly : object->layers().front()->lslices) {
|
||||||
if ((brim_type == BrimType::btOuterOnly || brim_type == BrimType::btOuterAndInner) && is_top_outer_brim)
|
if ((brim_type == BrimType::btOuterOnly || brim_type == BrimType::btOuterAndInner) && is_top_outer_brim)
|
||||||
append(brim_area_object, diff_ex(offset_ex(ex_poly.contour, brim_width + brim_offset), offset_ex(ex_poly.contour, brim_offset)));
|
append(brim_area_object, diff_ex(offset(ex_poly.contour, brim_width + brim_offset), offset(ex_poly.contour, brim_offset)));
|
||||||
|
|
||||||
if (brim_type == BrimType::btOuterOnly || brim_type == BrimType::btNoBrim)
|
if (brim_type == BrimType::btOuterOnly || brim_type == BrimType::btNoBrim)
|
||||||
append(no_brim_area_object, offset(ex_poly.holes, -no_brim_offset));
|
append(no_brim_area_object, offset(ex_poly.holes, -no_brim_offset));
|
||||||
|
@ -156,7 +156,7 @@ static ExPolygons top_level_outer_brim_area(const Print &print, const ConstPrint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return diff_ex(to_polygons(std::move(brim_area)), no_brim_area);
|
return diff_ex(brim_area, no_brim_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ExPolygons inner_brim_area(const Print &print, const ConstPrintObjectPtrs &top_level_objects_with_brim, const float no_brim_offset)
|
static ExPolygons inner_brim_area(const Print &print, const ConstPrintObjectPtrs &top_level_objects_with_brim, const float no_brim_offset)
|
||||||
|
@ -183,14 +183,14 @@ static ExPolygons inner_brim_area(const Print &print, const ConstPrintObjectPtrs
|
||||||
if (top_outer_brim)
|
if (top_outer_brim)
|
||||||
no_brim_area_object.emplace_back(ex_poly);
|
no_brim_area_object.emplace_back(ex_poly);
|
||||||
else
|
else
|
||||||
append(brim_area_object, diff_ex(offset_ex(ex_poly.contour, brim_width + brim_offset), offset_ex(ex_poly.contour, brim_offset)));
|
append(brim_area_object, diff_ex(offset(ex_poly.contour, brim_width + brim_offset), offset(ex_poly.contour, brim_offset)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btOuterAndInner)
|
if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btOuterAndInner)
|
||||||
append(brim_area_object, diff_ex(offset_ex(ex_poly.holes, -brim_offset), offset_ex(ex_poly.holes, -brim_width - brim_offset)));
|
append(brim_area_object, diff_ex(offset_ex(ex_poly.holes, -brim_offset), offset_ex(ex_poly.holes, -brim_width - brim_offset)));
|
||||||
|
|
||||||
if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btNoBrim)
|
if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btNoBrim)
|
||||||
append(no_brim_area_object, offset_ex(ex_poly.contour, no_brim_offset));
|
append(no_brim_area_object, to_expolygons(offset(ex_poly.contour, no_brim_offset)));
|
||||||
|
|
||||||
if (brim_type == BrimType::btOuterOnly || brim_type == BrimType::btNoBrim)
|
if (brim_type == BrimType::btOuterOnly || brim_type == BrimType::btNoBrim)
|
||||||
append(no_brim_area_object, offset_ex(ex_poly.holes, -no_brim_offset));
|
append(no_brim_area_object, offset_ex(ex_poly.holes, -no_brim_offset));
|
||||||
|
@ -317,7 +317,7 @@ static void make_inner_brim(const Print &print, const ConstPrintObjectPtrs &top_
|
||||||
islands_ex = offset_ex(islands_ex, -float(flow.scaled_spacing()), jtSquare);
|
islands_ex = offset_ex(islands_ex, -float(flow.scaled_spacing()), jtSquare);
|
||||||
}
|
}
|
||||||
|
|
||||||
loops = union_pt_chained_outside_in(loops, false);
|
loops = union_pt_chained_outside_in(loops);
|
||||||
std::reverse(loops.begin(), loops.end());
|
std::reverse(loops.begin(), loops.end());
|
||||||
extrusion_entities_append_loops(brim.entities, std::move(loops), erSkirt, float(flow.mm3_per_mm()),
|
extrusion_entities_append_loops(brim.entities, std::move(loops), erSkirt, float(flow.mm3_per_mm()),
|
||||||
float(flow.width()), float(print.skirt_first_layer_height()));
|
float(flow.width()), float(print.skirt_first_layer_height()));
|
||||||
|
@ -342,7 +342,7 @@ ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cance
|
||||||
poly.douglas_peucker(SCALED_RESOLUTION);
|
poly.douglas_peucker(SCALED_RESOLUTION);
|
||||||
polygons_append(loops, offset(islands, -0.5f * float(flow.scaled_spacing())));
|
polygons_append(loops, offset(islands, -0.5f * float(flow.scaled_spacing())));
|
||||||
}
|
}
|
||||||
loops = union_pt_chained_outside_in(loops, false);
|
loops = union_pt_chained_outside_in(loops);
|
||||||
|
|
||||||
std::vector<Polylines> loops_pl_by_levels;
|
std::vector<Polylines> loops_pl_by_levels;
|
||||||
{
|
{
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -12,230 +12,350 @@ using Slic3r::ClipperLib::jtMiter;
|
||||||
using Slic3r::ClipperLib::jtRound;
|
using Slic3r::ClipperLib::jtRound;
|
||||||
using Slic3r::ClipperLib::jtSquare;
|
using Slic3r::ClipperLib::jtSquare;
|
||||||
|
|
||||||
|
static constexpr const float ClipperSafetyOffset = 10.f;
|
||||||
|
|
||||||
#define CLIPPERUTILS_UNSAFE_OFFSET
|
#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 {
|
namespace Slic3r {
|
||||||
|
|
||||||
//-----------------------------------------------------------
|
namespace ClipperUtils {
|
||||||
// legacy code from Clipper documentation
|
class PathsProviderIteratorBase {
|
||||||
void AddOuterPolyNodeToExPolygons(ClipperLib::PolyNode& polynode, Slic3r::ExPolygons *expolygons);
|
public:
|
||||||
Slic3r::ExPolygons PolyTreeToExPolygons(ClipperLib::PolyTree& polytree);
|
using value_type = Points;
|
||||||
//-----------------------------------------------------------
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using pointer = const Points*;
|
||||||
|
using reference = const Points&;
|
||||||
|
using iterator_category = std::input_iterator_tag;
|
||||||
|
};
|
||||||
|
|
||||||
ClipperLib::Path Slic3rMultiPoint_to_ClipperPath(const Slic3r::MultiPoint &input);
|
class EmptyPathsProvider {
|
||||||
ClipperLib::Paths Slic3rMultiPoints_to_ClipperPaths(const Polygons &input);
|
public:
|
||||||
ClipperLib::Paths Slic3rMultiPoints_to_ClipperPaths(const ExPolygons &input);
|
struct iterator : public PathsProviderIteratorBase {
|
||||||
ClipperLib::Paths Slic3rMultiPoints_to_ClipperPaths(const Polylines &input);
|
public:
|
||||||
Slic3r::Polygon ClipperPath_to_Slic3rPolygon(const ClipperLib::Path &input);
|
constexpr const Points& operator*() { assert(false); return s_empty_points; }
|
||||||
Slic3r::Polyline ClipperPath_to_Slic3rPolyline(const ClipperLib::Path &input);
|
// all iterators point to end.
|
||||||
Slic3r::Polygons ClipperPaths_to_Slic3rPolygons(const ClipperLib::Paths &input);
|
constexpr bool operator==(const iterator &rhs) const { return true; }
|
||||||
Slic3r::Polylines ClipperPaths_to_Slic3rPolylines(const ClipperLib::Paths &input);
|
constexpr bool operator!=(const iterator &rhs) const { return false; }
|
||||||
Slic3r::ExPolygons ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input);
|
constexpr const Points& operator++(int) { assert(false); return s_empty_points; }
|
||||||
|
constexpr iterator& operator++() { assert(false); return *this; }
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr EmptyPathsProvider() {}
|
||||||
|
static constexpr iterator cend() throw() { return iterator{}; }
|
||||||
|
static constexpr iterator end() throw() { return cend(); }
|
||||||
|
static constexpr iterator cbegin() throw() { return cend(); }
|
||||||
|
static constexpr iterator begin() throw() { return cend(); }
|
||||||
|
static constexpr size_t size() throw() { return 0; }
|
||||||
|
|
||||||
|
static Points &s_empty_points;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SinglePathProvider {
|
||||||
|
public:
|
||||||
|
SinglePathProvider(const Points &points) : m_points(points) {}
|
||||||
|
|
||||||
|
struct iterator : public PathsProviderIteratorBase {
|
||||||
|
public:
|
||||||
|
explicit iterator(const Points &points) : m_ptr(&points) {}
|
||||||
|
const Points& operator*() const { return *m_ptr; }
|
||||||
|
bool operator==(const iterator &rhs) const { return m_ptr == rhs.m_ptr; }
|
||||||
|
bool operator!=(const iterator &rhs) const { return !(*this == rhs); }
|
||||||
|
const Points& operator++(int) { auto out = m_ptr; m_ptr = &s_end; return *out; }
|
||||||
|
iterator& operator++() { m_ptr = &s_end; return *this; }
|
||||||
|
private:
|
||||||
|
const Points *m_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
iterator cbegin() const { return iterator(m_points); }
|
||||||
|
iterator begin() const { return this->cbegin(); }
|
||||||
|
iterator cend() const { return iterator(s_end); }
|
||||||
|
iterator end() const { return this->cend(); }
|
||||||
|
size_t size() const { return 1; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Points &m_points;
|
||||||
|
static Points s_end;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename MultiPointType>
|
||||||
|
class MultiPointsProvider {
|
||||||
|
public:
|
||||||
|
MultiPointsProvider(const std::vector<MultiPointType> &multipoints) : m_multipoints(multipoints) {}
|
||||||
|
|
||||||
|
struct iterator : public PathsProviderIteratorBase {
|
||||||
|
public:
|
||||||
|
explicit iterator(typename std::vector<MultiPointType>::const_iterator it) : m_it(it) {}
|
||||||
|
const Points& operator*() const { return m_it->points; }
|
||||||
|
bool operator==(const iterator &rhs) const { return m_it == rhs.m_it; }
|
||||||
|
bool operator!=(const iterator &rhs) const { return !(*this == rhs); }
|
||||||
|
const Points& operator++(int) { return (m_it ++)->points; }
|
||||||
|
iterator& operator++() { ++ m_it; return *this; }
|
||||||
|
private:
|
||||||
|
typename std::vector<MultiPointType>::const_iterator m_it;
|
||||||
|
};
|
||||||
|
|
||||||
|
iterator cbegin() const { return iterator(m_multipoints.begin()); }
|
||||||
|
iterator begin() const { return this->cbegin(); }
|
||||||
|
iterator cend() const { return iterator(m_multipoints.end()); }
|
||||||
|
iterator end() const { return this->cend(); }
|
||||||
|
size_t size() const { return m_multipoints.size(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::vector<MultiPointType> &m_multipoints;
|
||||||
|
};
|
||||||
|
|
||||||
|
using PolygonsProvider = MultiPointsProvider<Polygon>;
|
||||||
|
using PolylinesProvider = MultiPointsProvider<Polyline>;
|
||||||
|
|
||||||
|
struct ExPolygonProvider {
|
||||||
|
ExPolygonProvider(const ExPolygon &expoly) : m_expoly(expoly) {}
|
||||||
|
|
||||||
|
struct iterator : public PathsProviderIteratorBase {
|
||||||
|
public:
|
||||||
|
explicit iterator(const ExPolygon &expoly, int idx) : m_expoly(expoly), m_idx(idx) {}
|
||||||
|
const Points& operator*() const { return (m_idx == 0) ? m_expoly.contour.points : m_expoly.holes[m_idx - 1].points; }
|
||||||
|
bool operator==(const iterator &rhs) const { assert(m_expoly == rhs.m_expoly); return m_idx == rhs.m_idx; }
|
||||||
|
bool operator!=(const iterator &rhs) const { return !(*this == rhs); }
|
||||||
|
const Points& operator++(int) { const Points &out = **this; ++ m_idx; return out; }
|
||||||
|
iterator& operator++() { ++ m_idx; return *this; }
|
||||||
|
private:
|
||||||
|
const ExPolygon &m_expoly;
|
||||||
|
int m_idx;
|
||||||
|
};
|
||||||
|
|
||||||
|
iterator cbegin() const { return iterator(m_expoly, 0); }
|
||||||
|
iterator begin() const { return this->cbegin(); }
|
||||||
|
iterator cend() const { return iterator(m_expoly, m_expoly.holes.size() + 1); }
|
||||||
|
iterator end() const { return this->cend(); }
|
||||||
|
size_t size() const { return m_expoly.holes.size() + 1; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const ExPolygon &m_expoly;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExPolygonsProvider {
|
||||||
|
ExPolygonsProvider(const ExPolygons &expolygons) : m_expolygons(expolygons) {
|
||||||
|
m_size = 0;
|
||||||
|
for (const ExPolygon &expoly : expolygons)
|
||||||
|
m_size += expoly.holes.size() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct iterator : public PathsProviderIteratorBase {
|
||||||
|
public:
|
||||||
|
explicit iterator(ExPolygons::const_iterator it) : m_it_expolygon(it), m_idx_contour(0) {}
|
||||||
|
const Points& operator*() const { return (m_idx_contour == 0) ? m_it_expolygon->contour.points : m_it_expolygon->holes[m_idx_contour - 1].points; }
|
||||||
|
bool operator==(const iterator &rhs) const { return m_it_expolygon == rhs.m_it_expolygon && m_idx_contour == rhs.m_idx_contour; }
|
||||||
|
bool operator!=(const iterator &rhs) const { return !(*this == rhs); }
|
||||||
|
iterator& operator++() {
|
||||||
|
if (++ m_idx_contour == m_it_expolygon->holes.size() + 1) {
|
||||||
|
++ m_it_expolygon;
|
||||||
|
m_idx_contour = 0;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
const Points& operator++(int) {
|
||||||
|
const Points &out = **this;
|
||||||
|
++ (*this);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
ExPolygons::const_iterator m_it_expolygon;
|
||||||
|
size_t m_idx_contour;
|
||||||
|
};
|
||||||
|
|
||||||
|
iterator cbegin() const { return iterator(m_expolygons.cbegin()); }
|
||||||
|
iterator begin() const { return this->cbegin(); }
|
||||||
|
iterator cend() const { return iterator(m_expolygons.cend()); }
|
||||||
|
iterator end() const { return this->cend(); }
|
||||||
|
size_t size() const { return m_size; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const ExPolygons &m_expolygons;
|
||||||
|
size_t m_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SurfacesProvider {
|
||||||
|
SurfacesProvider(const Surfaces &surfaces) : m_surfaces(surfaces) {
|
||||||
|
m_size = 0;
|
||||||
|
for (const Surface &surface : surfaces)
|
||||||
|
m_size += surface.expolygon.holes.size() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct iterator : public PathsProviderIteratorBase {
|
||||||
|
public:
|
||||||
|
explicit iterator(Surfaces::const_iterator it) : m_it_surface(it), m_idx_contour(0) {}
|
||||||
|
const Points& operator*() const { return (m_idx_contour == 0) ? m_it_surface->expolygon.contour.points : m_it_surface->expolygon.holes[m_idx_contour - 1].points; }
|
||||||
|
bool operator==(const iterator &rhs) const { return m_it_surface == rhs.m_it_surface && m_idx_contour == rhs.m_idx_contour; }
|
||||||
|
bool operator!=(const iterator &rhs) const { return !(*this == rhs); }
|
||||||
|
iterator& operator++() {
|
||||||
|
if (++ m_idx_contour == m_it_surface->expolygon.holes.size() + 1) {
|
||||||
|
++ m_it_surface;
|
||||||
|
m_idx_contour = 0;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
const Points& operator++(int) {
|
||||||
|
const Points &out = **this;
|
||||||
|
++ (*this);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
Surfaces::const_iterator m_it_surface;
|
||||||
|
size_t m_idx_contour;
|
||||||
|
};
|
||||||
|
|
||||||
|
iterator cbegin() const { return iterator(m_surfaces.cbegin()); }
|
||||||
|
iterator begin() const { return this->cbegin(); }
|
||||||
|
iterator cend() const { return iterator(m_surfaces.cend()); }
|
||||||
|
iterator end() const { return this->cend(); }
|
||||||
|
size_t size() const { return m_size; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Surfaces &m_surfaces;
|
||||||
|
size_t m_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SurfacesPtrProvider {
|
||||||
|
SurfacesPtrProvider(const SurfacesPtr &surfaces) : m_surfaces(surfaces) {
|
||||||
|
m_size = 0;
|
||||||
|
for (const Surface *surface : surfaces)
|
||||||
|
m_size += surface->expolygon.holes.size() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct iterator : public PathsProviderIteratorBase {
|
||||||
|
public:
|
||||||
|
explicit iterator(SurfacesPtr::const_iterator it) : m_it_surface(it), m_idx_contour(0) {}
|
||||||
|
const Points& operator*() const { return (m_idx_contour == 0) ? (*m_it_surface)->expolygon.contour.points : (*m_it_surface)->expolygon.holes[m_idx_contour - 1].points; }
|
||||||
|
bool operator==(const iterator &rhs) const { return m_it_surface == rhs.m_it_surface && m_idx_contour == rhs.m_idx_contour; }
|
||||||
|
bool operator!=(const iterator &rhs) const { return !(*this == rhs); }
|
||||||
|
iterator& operator++() {
|
||||||
|
if (++ m_idx_contour == (*m_it_surface)->expolygon.holes.size() + 1) {
|
||||||
|
++ m_it_surface;
|
||||||
|
m_idx_contour = 0;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
const Points& operator++(int) {
|
||||||
|
const Points &out = **this;
|
||||||
|
++ (*this);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
SurfacesPtr::const_iterator m_it_surface;
|
||||||
|
size_t m_idx_contour;
|
||||||
|
};
|
||||||
|
|
||||||
|
iterator cbegin() const { return iterator(m_surfaces.cbegin()); }
|
||||||
|
iterator begin() const { return this->cbegin(); }
|
||||||
|
iterator cend() const { return iterator(m_surfaces.cend()); }
|
||||||
|
iterator end() const { return this->cend(); }
|
||||||
|
size_t size() const { return m_size; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const SurfacesPtr &m_surfaces;
|
||||||
|
size_t m_size;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ExPolygons ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input);
|
||||||
|
|
||||||
// offset Polygons
|
// offset Polygons
|
||||||
ClipperLib::Paths _offset(ClipperLib::Path &&input, ClipperLib::EndType endType, const float delta, ClipperLib::JoinType joinType, double miterLimit);
|
Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
|
||||||
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
|
#ifdef CLIPPERUTILS_UNSAFE_OFFSET
|
||||||
inline Slic3r::Polygons offset(const Slic3r::Polygons &polygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
|
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
|
#endif // CLIPPERUTILS_UNSAFE_OFFSET
|
||||||
|
|
||||||
// offset Polylines
|
// offset Polylines
|
||||||
inline Slic3r::Polygons offset(const Slic3r::Polyline &polyline, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtSquare, double miterLimit = 3)
|
Slic3r::Polygons offset(const Slic3r::Polyline &polyline, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtSquare, double miterLimit = 3);
|
||||||
{ return ClipperPaths_to_Slic3rPolygons(_offset(Slic3rMultiPoint_to_ClipperPath(polyline), ClipperLib::etOpenButt, delta, joinType, miterLimit)); }
|
Slic3r::Polygons offset(const Slic3r::Polylines &polylines, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtSquare, double miterLimit = 3);
|
||||||
inline Slic3r::Polygons offset(const Slic3r::Polylines &polylines, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtSquare, double miterLimit = 3)
|
Slic3r::Polygons offset(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
|
||||||
{ return ClipperPaths_to_Slic3rPolygons(_offset(Slic3rMultiPoints_to_ClipperPaths(polylines), ClipperLib::etOpenButt, delta, joinType, miterLimit)); }
|
Slic3r::Polygons offset(const Slic3r::ExPolygons &expolygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
|
||||||
|
Slic3r::Polygons offset(const Slic3r::Surfaces &surfaces, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
|
||||||
|
Slic3r::Polygons offset(const Slic3r::SurfacesPtr &surfaces, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
|
||||||
|
Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
|
||||||
|
Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygons &expolygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
|
||||||
|
Slic3r::ExPolygons offset_ex(const Slic3r::Surfaces &surfaces, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
|
||||||
|
|
||||||
// offset expolygons and surfaces
|
Slic3r::Polygons offset2(const Slic3r::ExPolygons &expolygons, const float delta1, const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
|
||||||
ClipperLib::Paths _offset(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType, double miterLimit);
|
Slic3r::ExPolygons offset2_ex(const Slic3r::ExPolygons &expolygons, const float delta1, const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
|
||||||
ClipperLib::Paths _offset(const Slic3r::ExPolygons &expolygons, const float delta, ClipperLib::JoinType joinType, double miterLimit);
|
|
||||||
inline Slic3r::Polygons offset(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
|
|
||||||
{ return ClipperPaths_to_Slic3rPolygons(_offset(expolygon, delta, joinType, miterLimit)); }
|
|
||||||
inline Slic3r::Polygons offset(const Slic3r::ExPolygons &expolygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
|
|
||||||
{ 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
|
#ifdef CLIPPERUTILS_UNSAFE_OFFSET
|
||||||
inline Slic3r::ExPolygons offset_ex(const Slic3r::Polygons &polygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
|
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)); }
|
ClipperLib::Paths _offset2(const Slic3r::Polygons &polygons, const float delta1, const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
|
||||||
|
Slic3r::Polygons offset2(const Slic3r::Polygons &polygons, const float delta1, const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
|
||||||
|
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
|
#endif // CLIPPERUTILS_UNSAFE_OFFSET
|
||||||
|
|
||||||
inline Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
|
Slic3r::Lines _clipper_ln(ClipperLib::ClipType clipType, const Slic3r::Lines &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||||
{ 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
|
Slic3r::Polygons diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||||
ClipperLib::Paths _offset2(const Slic3r::Polygons &polygons, const float delta1,
|
Slic3r::Polygons diff(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||||
const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
|
Slic3r::Polygons diff(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
|
||||||
double miterLimit = 3);
|
Slic3r::ExPolygons diff_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||||
Slic3r::Polygons offset2(const Slic3r::Polygons &polygons, const float delta1,
|
Slic3r::ExPolygons diff_ex(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
|
||||||
const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
|
Slic3r::ExPolygons diff_ex(const Slic3r::Polygons &subject, const Slic3r::Surfaces &clip, bool do_safety_offset = false);
|
||||||
double miterLimit = 3);
|
Slic3r::ExPolygons diff_ex(const Slic3r::Polygon &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
|
||||||
Slic3r::ExPolygons offset2_ex(const Slic3r::Polygons &polygons, const float delta1,
|
Slic3r::ExPolygons diff_ex(const Slic3r::ExPolygon &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||||
const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
|
Slic3r::ExPolygons diff_ex(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||||
double miterLimit = 3);
|
Slic3r::ExPolygons diff_ex(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
|
||||||
#endif // CLIPPERUTILS_UNSAFE_OFFSET
|
Slic3r::ExPolygons diff_ex(const Slic3r::Surfaces &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||||
|
Slic3r::ExPolygons diff_ex(const Slic3r::Surfaces &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
|
||||||
|
Slic3r::ExPolygons diff_ex(const Slic3r::ExPolygons &subject, const Slic3r::Surfaces &clip, bool do_safety_offset = false);
|
||||||
|
Slic3r::ExPolygons diff_ex(const Slic3r::Surfaces &subject, const Slic3r::Surfaces &clip, bool do_safety_offset = false);
|
||||||
|
Slic3r::ExPolygons diff_ex(const Slic3r::SurfacesPtr &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||||
|
Slic3r::Polylines diff_pl(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||||
|
Slic3r::Polylines diff_pl(const Slic3r::Polylines &subject, const Slic3r::ExPolygon &clip, bool do_safety_offset = false);
|
||||||
|
Slic3r::Polylines diff_pl(const Slic3r::Polylines &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
|
||||||
|
Slic3r::Polylines diff_pl(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||||
|
|
||||||
Slic3r::ExPolygons offset2_ex(const Slic3r::ExPolygons &expolygons, const float delta1,
|
inline Slic3r::Lines diff_ln(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false)
|
||||||
const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
|
|
||||||
double miterLimit = 3);
|
|
||||||
|
|
||||||
Slic3r::Polygons _clipper(ClipperLib::ClipType clipType,
|
|
||||||
const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false);
|
|
||||||
Slic3r::ExPolygons _clipper_ex(ClipperLib::ClipType clipType,
|
|
||||||
const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false);
|
|
||||||
Slic3r::Polylines _clipper_pl(ClipperLib::ClipType clipType,
|
|
||||||
const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false);
|
|
||||||
Slic3r::Polylines _clipper_pl(ClipperLib::ClipType clipType,
|
|
||||||
const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false);
|
|
||||||
Slic3r::Lines _clipper_ln(ClipperLib::ClipType clipType,
|
|
||||||
const Slic3r::Lines &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false);
|
|
||||||
|
|
||||||
// diff
|
|
||||||
inline Slic3r::Polygons
|
|
||||||
diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
|
|
||||||
{
|
{
|
||||||
return _clipper(ClipperLib::ctDifference, subject, clip, safety_offset_);
|
return _clipper_ln(ClipperLib::ctDifference, subject, clip, do_safety_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Slic3r::ExPolygons
|
Slic3r::Polygons intersection(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||||
diff_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
|
Slic3r::Polygons intersection(const Slic3r::ExPolygon &subject, const Slic3r::ExPolygon &clip, bool do_safety_offset = false);
|
||||||
|
Slic3r::Polygons intersection(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||||
|
Slic3r::Polygons intersection(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
|
||||||
|
Slic3r::Polygons intersection(const Slic3r::Surfaces &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||||
|
Slic3r::Polygons intersection(const Slic3r::Surfaces &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
|
||||||
|
Slic3r::ExPolygons intersection_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||||
|
Slic3r::ExPolygons intersection_ex(const Slic3r::ExPolygon &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||||
|
Slic3r::ExPolygons intersection_ex(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
|
||||||
|
Slic3r::ExPolygons intersection_ex(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||||
|
Slic3r::ExPolygons intersection_ex(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
|
||||||
|
Slic3r::ExPolygons intersection_ex(const Slic3r::Surfaces &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||||
|
Slic3r::ExPolygons intersection_ex(const Slic3r::Surfaces &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
|
||||||
|
Slic3r::ExPolygons intersection_ex(const Slic3r::Surfaces &subject, const Slic3r::Surfaces &clip, bool do_safety_offset = false);
|
||||||
|
Slic3r::ExPolygons intersection_ex(const Slic3r::SurfacesPtr &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
|
||||||
|
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||||
|
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
|
||||||
|
Slic3r::Polylines intersection_pl(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||||
|
|
||||||
|
inline Slic3r::Lines intersection_ln(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false)
|
||||||
{
|
{
|
||||||
return _clipper_ex(ClipperLib::ctDifference, subject, clip, safety_offset_);
|
return _clipper_ln(ClipperLib::ctIntersection, subject, clip, do_safety_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Slic3r::ExPolygons
|
inline Slic3r::Lines intersection_ln(const Slic3r::Line &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false)
|
||||||
diff_ex(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_ = false)
|
|
||||||
{
|
|
||||||
return _clipper_ex(ClipperLib::ctDifference, to_polygons(subject), to_polygons(clip), safety_offset_);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Slic3r::Polygons
|
|
||||||
diff(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_ = false)
|
|
||||||
{
|
|
||||||
return _clipper(ClipperLib::ctDifference, to_polygons(subject), to_polygons(clip), safety_offset_);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Slic3r::Polylines
|
|
||||||
diff_pl(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
|
|
||||||
{
|
|
||||||
return _clipper_pl(ClipperLib::ctDifference, subject, clip, safety_offset_);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Slic3r::Polylines
|
|
||||||
diff_pl(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
|
|
||||||
{
|
|
||||||
return _clipper_pl(ClipperLib::ctDifference, subject, clip, safety_offset_);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Slic3r::Lines
|
|
||||||
diff_ln(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
|
|
||||||
{
|
|
||||||
return _clipper_ln(ClipperLib::ctDifference, subject, clip, safety_offset_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// intersection
|
|
||||||
inline Slic3r::Polygons
|
|
||||||
intersection(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
|
|
||||||
{
|
|
||||||
return _clipper(ClipperLib::ctIntersection, subject, clip, safety_offset_);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Slic3r::ExPolygons
|
|
||||||
intersection_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
|
|
||||||
{
|
|
||||||
return _clipper_ex(ClipperLib::ctIntersection, subject, clip, safety_offset_);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Slic3r::ExPolygons
|
|
||||||
intersection_ex(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_ = false)
|
|
||||||
{
|
|
||||||
return _clipper_ex(ClipperLib::ctIntersection, to_polygons(subject), to_polygons(clip), safety_offset_);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Slic3r::Polygons
|
|
||||||
intersection(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_ = false)
|
|
||||||
{
|
|
||||||
return _clipper(ClipperLib::ctIntersection, to_polygons(subject), to_polygons(clip), safety_offset_);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Slic3r::Polylines
|
|
||||||
intersection_pl(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
|
|
||||||
{
|
|
||||||
return _clipper_pl(ClipperLib::ctIntersection, subject, clip, safety_offset_);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Slic3r::Polylines
|
|
||||||
intersection_pl(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
|
|
||||||
{
|
|
||||||
return _clipper_pl(ClipperLib::ctIntersection, subject, clip, safety_offset_);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Slic3r::Lines intersection_ln(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
|
|
||||||
{
|
|
||||||
return _clipper_ln(ClipperLib::ctIntersection, subject, clip, safety_offset_);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Slic3r::Lines intersection_ln(const Slic3r::Line &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
|
|
||||||
{
|
{
|
||||||
Slic3r::Lines lines;
|
Slic3r::Lines lines;
|
||||||
lines.emplace_back(subject);
|
lines.emplace_back(subject);
|
||||||
return _clipper_ln(ClipperLib::ctIntersection, lines, clip, safety_offset_);
|
return _clipper_ln(ClipperLib::ctIntersection, lines, clip, do_safety_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// union
|
Slic3r::Polygons union_(const Slic3r::Polygons &subject, bool do_safety_offset = false);
|
||||||
inline Slic3r::Polygons union_(const Slic3r::Polygons &subject, bool safety_offset_ = false)
|
Slic3r::Polygons union_(const Slic3r::ExPolygons &subject, bool do_safety_offset = false);
|
||||||
{
|
Slic3r::Polygons union_(const Slic3r::Polygons &subject, const Slic3r::Polygons &subject2, bool do_safety_offset = false);
|
||||||
return _clipper(ClipperLib::ctUnion, subject, Slic3r::Polygons(), safety_offset_);
|
Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject, bool do_safety_offset = false);
|
||||||
}
|
Slic3r::ExPolygons union_ex(const Slic3r::ExPolygons &subject);
|
||||||
|
Slic3r::ExPolygons union_ex(const Slic3r::Surfaces &subject);
|
||||||
|
|
||||||
inline Slic3r::Polygons union_(const Slic3r::Polygons &subject, const Slic3r::Polygons &subject2, bool safety_offset_ = false)
|
ClipperLib::PolyTree union_pt(const Slic3r::Polygons &subject);
|
||||||
{
|
ClipperLib::PolyTree union_pt(const Slic3r::ExPolygons &subject);
|
||||||
return _clipper(ClipperLib::ctUnion, subject, subject2, safety_offset_);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject, bool safety_offset_ = false)
|
Slic3r::Polygons union_pt_chained_outside_in(const Slic3r::Polygons &subject);
|
||||||
{
|
|
||||||
return _clipper_ex(ClipperLib::ctUnion, subject, Slic3r::Polygons(), safety_offset_);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Slic3r::ExPolygons union_ex(const Slic3r::ExPolygons &subject, bool safety_offset_ = false)
|
|
||||||
{
|
|
||||||
return _clipper_ex(ClipperLib::ctUnion, to_polygons(subject), Slic3r::Polygons(), safety_offset_);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Slic3r::ExPolygons union_ex(const Slic3r::Surfaces &subject, bool safety_offset_ = false)
|
|
||||||
{
|
|
||||||
return _clipper_ex(ClipperLib::ctUnion, to_polygons(subject), Slic3r::Polygons(), safety_offset_);
|
|
||||||
}
|
|
||||||
|
|
||||||
ClipperLib::PolyTree union_pt(const Slic3r::Polygons &subject, bool safety_offset_ = false);
|
|
||||||
ClipperLib::PolyTree union_pt(const Slic3r::ExPolygons &subject, bool safety_offset_ = false);
|
|
||||||
ClipperLib::PolyTree union_pt(Slic3r::Polygons &&subject, bool safety_offset_ = false);
|
|
||||||
ClipperLib::PolyTree union_pt(Slic3r::ExPolygons &&subject, bool safety_offset_ = false);
|
|
||||||
|
|
||||||
Slic3r::Polygons union_pt_chained_outside_in(const Slic3r::Polygons &subject, bool safety_offset_ = false);
|
|
||||||
|
|
||||||
ClipperLib::PolyNodes order_nodes(const ClipperLib::PolyNodes &nodes);
|
ClipperLib::PolyNodes order_nodes(const ClipperLib::PolyNodes &nodes);
|
||||||
|
|
||||||
|
@ -283,7 +403,7 @@ void traverse_pt(const ClipperLib::PolyNode *tree, Polygons *out)
|
||||||
if (!tree) return; // terminates recursion
|
if (!tree) return; // terminates recursion
|
||||||
|
|
||||||
// Push the contour of the current level
|
// Push the contour of the current level
|
||||||
out->emplace_back(ClipperPath_to_Slic3rPolygon(tree->Contour));
|
out->emplace_back(tree->Contour);
|
||||||
|
|
||||||
// Do the recursion for all the children.
|
// Do the recursion for all the children.
|
||||||
traverse_pt<ordering>(tree->Childs, out);
|
traverse_pt<ordering>(tree->Childs, out);
|
||||||
|
@ -302,13 +422,13 @@ void traverse_pt(const ClipperLib::PolyNode *tree, ExPolygons *out)
|
||||||
}
|
}
|
||||||
|
|
||||||
ExPolygon level;
|
ExPolygon level;
|
||||||
level.contour = ClipperPath_to_Slic3rPolygon(tree->Contour);
|
level.contour.points = tree->Contour;
|
||||||
|
|
||||||
foreach_node<ordering>(tree->Childs,
|
foreach_node<ordering>(tree->Childs,
|
||||||
[out, &level] (const ClipperLib::PolyNode *node) {
|
[out, &level] (const ClipperLib::PolyNode *node) {
|
||||||
|
|
||||||
// Holes are collected here.
|
// Holes are collected here.
|
||||||
level.holes.emplace_back(ClipperPath_to_Slic3rPolygon(node->Contour));
|
level.holes.emplace_back(node->Contour);
|
||||||
|
|
||||||
// By doing a recursion, a new level expoly is created with the contour
|
// By doing a recursion, a new level expoly is created with the contour
|
||||||
// and holes of the lower level. Doing this for all the childs.
|
// and holes of the lower level. Doing this for all the childs.
|
||||||
|
@ -331,8 +451,6 @@ void traverse_pt(const ClipperLib::PolyNodes &nodes, ExOrJustPolygons *retval)
|
||||||
Slic3r::Polygons simplify_polygons(const Slic3r::Polygons &subject, bool preserve_collinear = false);
|
Slic3r::Polygons simplify_polygons(const Slic3r::Polygons &subject, bool preserve_collinear = false);
|
||||||
Slic3r::ExPolygons simplify_polygons_ex(const Slic3r::Polygons &subject, bool preserve_collinear = false);
|
Slic3r::ExPolygons simplify_polygons_ex(const Slic3r::Polygons &subject, bool preserve_collinear = false);
|
||||||
|
|
||||||
void safety_offset(ClipperLib::Paths* paths);
|
|
||||||
|
|
||||||
Polygons top_level_islands(const Slic3r::Polygons &polygons);
|
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);
|
ClipperLib::Path mittered_offset_path_scaled(const Points &contour, const std::vector<float> &deltas, double miter_limit);
|
||||||
|
|
|
@ -83,8 +83,8 @@ inline bool operator!=(const ExPolygon &lhs, const ExPolygon &rhs) { return lhs.
|
||||||
inline size_t number_polygons(const ExPolygons &expolys)
|
inline size_t number_polygons(const ExPolygons &expolys)
|
||||||
{
|
{
|
||||||
size_t n_polygons = 0;
|
size_t n_polygons = 0;
|
||||||
for (ExPolygons::const_iterator it = expolys.begin(); it != expolys.end(); ++ it)
|
for (const ExPolygon &ex : expolys)
|
||||||
n_polygons += it->holes.size() + 1;
|
n_polygons += ex.holes.size() + 1;
|
||||||
return n_polygons;
|
return n_polygons;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,12 +14,12 @@ namespace Slic3r {
|
||||||
|
|
||||||
void ExtrusionPath::intersect_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const
|
void ExtrusionPath::intersect_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const
|
||||||
{
|
{
|
||||||
this->_inflate_collection(intersection_pl((Polylines)polyline, to_polygons(collection.expolygons)), retval);
|
this->_inflate_collection(intersection_pl(Polylines{ polyline }, collection.expolygons), retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExtrusionPath::subtract_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const
|
void ExtrusionPath::subtract_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const
|
||||||
{
|
{
|
||||||
this->_inflate_collection(diff_pl((Polylines)this->polyline, to_polygons(collection.expolygons)), retval);
|
this->_inflate_collection(diff_pl(Polylines{ this->polyline }, collection.expolygons), retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExtrusionPath::clip_end(double distance)
|
void ExtrusionPath::clip_end(double distance)
|
||||||
|
|
|
@ -162,7 +162,7 @@ void Fill3DHoneycomb::_fill_surface_single(
|
||||||
pl.translate(bb.min);
|
pl.translate(bb.min);
|
||||||
|
|
||||||
// clip pattern to boundaries, chain the clipped polylines
|
// clip pattern to boundaries, chain the clipped polylines
|
||||||
polylines = intersection_pl(polylines, to_polygons(expolygon));
|
polylines = intersection_pl(polylines, expolygon);
|
||||||
|
|
||||||
// connect lines if needed
|
// connect lines if needed
|
||||||
if (params.dont_connect() || polylines.size() <= 1)
|
if (params.dont_connect() || polylines.size() <= 1)
|
||||||
|
|
|
@ -1368,7 +1368,7 @@ void Filler::_fill_surface_single(
|
||||||
all_polylines.reserve(lines.size());
|
all_polylines.reserve(lines.size());
|
||||||
std::transform(lines.begin(), lines.end(), std::back_inserter(all_polylines), [](const Line& l) { return Polyline{ l.a, l.b }; });
|
std::transform(lines.begin(), lines.end(), std::back_inserter(all_polylines), [](const Line& l) { return Polyline{ l.a, l.b }; });
|
||||||
// Crop all polylines
|
// Crop all polylines
|
||||||
all_polylines = intersection_pl(std::move(all_polylines), to_polygons(expolygon));
|
all_polylines = intersection_pl(std::move(all_polylines), expolygon);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ void FillConcentric::_fill_surface_single(
|
||||||
|
|
||||||
// generate paths from the outermost to the innermost, to avoid
|
// generate paths from the outermost to the innermost, to avoid
|
||||||
// adhesion problems of the first central tiny loops
|
// adhesion problems of the first central tiny loops
|
||||||
loops = union_pt_chained_outside_in(loops, false);
|
loops = union_pt_chained_outside_in(loops);
|
||||||
|
|
||||||
// split paths using a nearest neighbor search
|
// split paths using a nearest neighbor search
|
||||||
size_t iPathFirst = polylines_out.size();
|
size_t iPathFirst = polylines_out.size();
|
||||||
|
|
|
@ -180,7 +180,7 @@ void FillGyroid::_fill_surface_single(
|
||||||
for (Polyline &pl : polylines)
|
for (Polyline &pl : polylines)
|
||||||
pl.translate(bb.min);
|
pl.translate(bb.min);
|
||||||
|
|
||||||
polylines = intersection_pl(polylines, to_polygons(expolygon));
|
polylines = intersection_pl(polylines, expolygon);
|
||||||
|
|
||||||
if (! polylines.empty()) {
|
if (! polylines.empty()) {
|
||||||
// Remove very small bits, but be careful to not remove infill lines connecting thin walls!
|
// Remove very small bits, but be careful to not remove infill lines connecting thin walls!
|
||||||
|
|
|
@ -73,7 +73,7 @@ void FillHoneycomb::_fill_surface_single(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
all_polylines = intersection_pl(std::move(all_polylines), to_polygons(expolygon));
|
all_polylines = intersection_pl(std::move(all_polylines), expolygon);
|
||||||
if (params.dont_connect() || all_polylines.size() <= 1)
|
if (params.dont_connect() || all_polylines.size() <= 1)
|
||||||
append(polylines_out, chain_polylines(std::move(all_polylines)));
|
append(polylines_out, chain_polylines(std::move(all_polylines)));
|
||||||
else
|
else
|
||||||
|
|
|
@ -44,7 +44,7 @@ void FillPlanePath::_fill_surface_single(
|
||||||
coord_t(floor(pt.x() * distance_between_lines + 0.5)),
|
coord_t(floor(pt.x() * distance_between_lines + 0.5)),
|
||||||
coord_t(floor(pt.y() * distance_between_lines + 0.5))));
|
coord_t(floor(pt.y() * distance_between_lines + 0.5))));
|
||||||
// intersection(polylines_src, offset((Polygons)expolygon, scale_(0.02)), &polylines);
|
// intersection(polylines_src, offset((Polygons)expolygon, scale_(0.02)), &polylines);
|
||||||
polylines = intersection_pl(std::move(polylines), to_polygons(expolygon));
|
polylines = intersection_pl(std::move(polylines), expolygon);
|
||||||
Polylines chained;
|
Polylines chained;
|
||||||
if (params.dont_connect() || params.density > 0.5 || polylines.size() <= 1)
|
if (params.dont_connect() || params.density > 0.5 || polylines.size() <= 1)
|
||||||
chained = chain_polylines(std::move(polylines));
|
chained = chain_polylines(std::move(polylines));
|
||||||
|
|
|
@ -39,11 +39,11 @@ void Layer::make_slices()
|
||||||
ExPolygons slices;
|
ExPolygons slices;
|
||||||
if (m_regions.size() == 1) {
|
if (m_regions.size() == 1) {
|
||||||
// optimization: if we only have one region, take its slices
|
// optimization: if we only have one region, take its slices
|
||||||
slices = m_regions.front()->slices;
|
slices = to_expolygons(m_regions.front()->slices.surfaces);
|
||||||
} else {
|
} else {
|
||||||
Polygons slices_p;
|
Polygons slices_p;
|
||||||
for (LayerRegion *layerm : m_regions)
|
for (LayerRegion *layerm : m_regions)
|
||||||
polygons_append(slices_p, to_polygons(layerm->slices));
|
polygons_append(slices_p, to_polygons(layerm->slices.surfaces));
|
||||||
slices = union_ex(slices_p);
|
slices = union_ex(slices_p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ ExPolygons Layer::merged(float offset_scaled) const
|
||||||
const PrintRegionConfig &config = layerm->region()->config();
|
const PrintRegionConfig &config = layerm->region()->config();
|
||||||
// Our users learned to bend Slic3r to produce empty volumes to act as subtracters. Only add the region if it is non-empty.
|
// Our users learned to bend Slic3r to produce empty volumes to act as subtracters. Only add the region if it is non-empty.
|
||||||
if (config.bottom_solid_layers > 0 || config.top_solid_layers > 0 || config.fill_density > 0. || config.perimeters > 0)
|
if (config.bottom_solid_layers > 0 || config.top_solid_layers > 0 || config.fill_density > 0. || config.perimeters > 0)
|
||||||
append(polygons, offset(to_expolygons(layerm->slices.surfaces), offset_scaled));
|
append(polygons, offset(layerm->slices.surfaces, offset_scaled));
|
||||||
}
|
}
|
||||||
ExPolygons out = union_ex(polygons);
|
ExPolygons out = union_ex(polygons);
|
||||||
if (offset_scaled2 != 0.f)
|
if (offset_scaled2 != 0.f)
|
||||||
|
@ -185,7 +185,7 @@ void Layer::make_perimeters()
|
||||||
}
|
}
|
||||||
// merge the surfaces assigned to each group
|
// merge the surfaces assigned to each group
|
||||||
for (std::pair<const unsigned short,Surfaces> &surfaces_with_extra_perimeters : slices)
|
for (std::pair<const unsigned short,Surfaces> &surfaces_with_extra_perimeters : slices)
|
||||||
new_slices.append(offset_ex(to_expolygons(surfaces_with_extra_perimeters.second), 10.f), surfaces_with_extra_perimeters.second.front());
|
new_slices.append(offset_ex(surfaces_with_extra_perimeters.second, ClipperSafetyOffset), surfaces_with_extra_perimeters.second.front());
|
||||||
}
|
}
|
||||||
|
|
||||||
// make perimeters
|
// make perimeters
|
||||||
|
@ -196,7 +196,7 @@ void Layer::make_perimeters()
|
||||||
if (!fill_surfaces.surfaces.empty()) {
|
if (!fill_surfaces.surfaces.empty()) {
|
||||||
for (LayerRegionPtrs::iterator l = layerms.begin(); l != layerms.end(); ++l) {
|
for (LayerRegionPtrs::iterator l = layerms.begin(); l != layerms.end(); ++l) {
|
||||||
// Separate the fill surfaces.
|
// Separate the fill surfaces.
|
||||||
ExPolygons expp = intersection_ex(to_polygons(fill_surfaces), (*l)->slices);
|
ExPolygons expp = intersection_ex(fill_surfaces.surfaces, (*l)->slices.surfaces);
|
||||||
(*l)->fill_expolygons = expp;
|
(*l)->fill_expolygons = expp;
|
||||||
(*l)->fill_surfaces.set(std::move(expp), fill_surfaces.surfaces.front());
|
(*l)->fill_surfaces.set(std::move(expp), fill_surfaces.surfaces.front());
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,7 +196,7 @@ protected:
|
||||||
// between the raft and the object first layer.
|
// between the raft and the object first layer.
|
||||||
SupportLayer(size_t id, PrintObject *object, coordf_t height, coordf_t print_z, coordf_t slice_z) :
|
SupportLayer(size_t id, PrintObject *object, coordf_t height, coordf_t print_z, coordf_t slice_z) :
|
||||||
Layer(id, object, height, print_z, slice_z) {}
|
Layer(id, object, height, print_z, slice_z) {}
|
||||||
virtual ~SupportLayer() {}
|
virtual ~SupportLayer() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,19 +49,17 @@ void LayerRegion::slices_to_fill_surfaces_clipped()
|
||||||
// in place. However we're now only using its boundaries (which are invariant)
|
// in place. However we're now only using its boundaries (which are invariant)
|
||||||
// so we're safe. This guarantees idempotence of prepare_infill() also in case
|
// so we're safe. This guarantees idempotence of prepare_infill() also in case
|
||||||
// that combine_infill() turns some fill_surface into VOID surfaces.
|
// that combine_infill() turns some fill_surface into VOID surfaces.
|
||||||
// Polygons fill_boundaries = to_polygons(std::move(this->fill_surfaces));
|
|
||||||
Polygons fill_boundaries = to_polygons(this->fill_expolygons);
|
|
||||||
// Collect polygons per surface type.
|
// Collect polygons per surface type.
|
||||||
std::vector<Polygons> polygons_by_surface;
|
std::vector<SurfacesPtr> by_surface;
|
||||||
polygons_by_surface.assign(size_t(stCount), Polygons());
|
by_surface.assign(size_t(stCount), SurfacesPtr());
|
||||||
for (Surface &surface : this->slices.surfaces)
|
for (Surface &surface : this->slices.surfaces)
|
||||||
polygons_append(polygons_by_surface[(size_t)surface.surface_type], surface.expolygon);
|
by_surface[size_t(surface.surface_type)].emplace_back(&surface);
|
||||||
// Trim surfaces by the fill_boundaries.
|
// Trim surfaces by the fill_boundaries.
|
||||||
this->fill_surfaces.surfaces.clear();
|
this->fill_surfaces.surfaces.clear();
|
||||||
for (size_t surface_type = 0; surface_type < size_t(stCount); ++ surface_type) {
|
for (size_t surface_type = 0; surface_type < size_t(stCount); ++ surface_type) {
|
||||||
const Polygons &polygons = polygons_by_surface[surface_type];
|
const SurfacesPtr &this_surfaces = by_surface[surface_type];
|
||||||
if (! polygons.empty())
|
if (! this_surfaces.empty())
|
||||||
this->fill_surfaces.append(intersection_ex(polygons, fill_boundaries), SurfaceType(surface_type));
|
this->fill_surfaces.append(intersection_ex(this_surfaces, this->fill_expolygons), SurfaceType(surface_type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,7 +219,7 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
|
||||||
BOOST_LOG_TRIVIAL(trace) << "Bridge did not fall into the source region!";
|
BOOST_LOG_TRIVIAL(trace) << "Bridge did not fall into the source region!";
|
||||||
} else {
|
} else {
|
||||||
// Found an island, to which this bridge region belongs. Trim it,
|
// Found an island, to which this bridge region belongs. Trim it,
|
||||||
polys = intersection(polys, to_polygons(fill_boundaries_ex[idx_island]));
|
polys = intersection(polys, fill_boundaries_ex[idx_island]);
|
||||||
}
|
}
|
||||||
bridge_bboxes.push_back(get_extents(polys));
|
bridge_bboxes.push_back(get_extents(polys));
|
||||||
bridges_grown.push_back(std::move(polys));
|
bridges_grown.push_back(std::move(polys));
|
||||||
|
@ -325,11 +323,11 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
|
||||||
if (s1.empty())
|
if (s1.empty())
|
||||||
continue;
|
continue;
|
||||||
Polygons polys;
|
Polygons polys;
|
||||||
polygons_append(polys, std::move(s1));
|
polygons_append(polys, to_polygons(std::move(s1)));
|
||||||
for (size_t j = i + 1; j < top.size(); ++ j) {
|
for (size_t j = i + 1; j < top.size(); ++ j) {
|
||||||
Surface &s2 = top[j];
|
Surface &s2 = top[j];
|
||||||
if (! s2.empty() && surfaces_could_merge(s1, s2)) {
|
if (! s2.empty() && surfaces_could_merge(s1, s2)) {
|
||||||
polygons_append(polys, std::move(s2));
|
polygons_append(polys, to_polygons(std::move(s2)));
|
||||||
s2.clear();
|
s2.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -351,11 +349,11 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
|
||||||
if (s1.empty())
|
if (s1.empty())
|
||||||
continue;
|
continue;
|
||||||
Polygons polys;
|
Polygons polys;
|
||||||
polygons_append(polys, std::move(s1));
|
polygons_append(polys, to_polygons(std::move(s1)));
|
||||||
for (size_t j = i + 1; j < internal.size(); ++ j) {
|
for (size_t j = i + 1; j < internal.size(); ++ j) {
|
||||||
Surface &s2 = internal[j];
|
Surface &s2 = internal[j];
|
||||||
if (! s2.empty() && surfaces_could_merge(s1, s2)) {
|
if (! s2.empty() && surfaces_could_merge(s1, s2)) {
|
||||||
polygons_append(polys, std::move(s2));
|
polygons_append(polys, to_polygons(std::move(s2)));
|
||||||
s2.clear();
|
s2.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -423,7 +421,7 @@ void LayerRegion::trim_surfaces(const Polygons &trimming_polygons)
|
||||||
for (const Surface &surface : this->slices.surfaces)
|
for (const Surface &surface : this->slices.surfaces)
|
||||||
assert(surface.surface_type == stInternal);
|
assert(surface.surface_type == stInternal);
|
||||||
#endif /* NDEBUG */
|
#endif /* NDEBUG */
|
||||||
this->slices.set(intersection_ex(to_polygons(std::move(this->slices.surfaces)), trimming_polygons, false), stInternal);
|
this->slices.set(intersection_ex(this->slices.surfaces, trimming_polygons), stInternal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerRegion::elephant_foot_compensation_step(const float elephant_foot_compensation_perimeter_step, const Polygons &trimming_polygons)
|
void LayerRegion::elephant_foot_compensation_step(const float elephant_foot_compensation_perimeter_step, const Polygons &trimming_polygons)
|
||||||
|
@ -432,10 +430,9 @@ void LayerRegion::elephant_foot_compensation_step(const float elephant_foot_comp
|
||||||
for (const Surface &surface : this->slices.surfaces)
|
for (const Surface &surface : this->slices.surfaces)
|
||||||
assert(surface.surface_type == stInternal);
|
assert(surface.surface_type == stInternal);
|
||||||
#endif /* NDEBUG */
|
#endif /* NDEBUG */
|
||||||
ExPolygons slices_expolygons = to_expolygons(std::move(this->slices.surfaces));
|
ExPolygons surfaces = to_expolygons(std::move(this->slices.surfaces));
|
||||||
Polygons slices_polygons = to_polygons(slices_expolygons);
|
Polygons tmp = intersection(surfaces, trimming_polygons);
|
||||||
Polygons tmp = intersection(slices_polygons, trimming_polygons, false);
|
append(tmp, diff(surfaces, offset(offset_ex(surfaces, -elephant_foot_compensation_perimeter_step), elephant_foot_compensation_perimeter_step)));
|
||||||
append(tmp, diff(slices_polygons, offset(offset_ex(slices_expolygons, -elephant_foot_compensation_perimeter_step), elephant_foot_compensation_perimeter_step)));
|
|
||||||
this->slices.set(union_ex(tmp), stInternal);
|
this->slices.set(union_ex(tmp), stInternal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -349,9 +349,7 @@ void PerimeterGenerator::process()
|
||||||
coord_t min_width = coord_t(scale_(this->ext_perimeter_flow.nozzle_diameter() / 3));
|
coord_t min_width = coord_t(scale_(this->ext_perimeter_flow.nozzle_diameter() / 3));
|
||||||
ExPolygons expp = offset2_ex(
|
ExPolygons expp = offset2_ex(
|
||||||
// medial axis requires non-overlapping geometry
|
// medial axis requires non-overlapping geometry
|
||||||
diff_ex(to_polygons(last),
|
diff_ex(last, offset(offsets, float(ext_perimeter_width / 2.)), true),
|
||||||
offset(offsets, float(ext_perimeter_width / 2.)),
|
|
||||||
true),
|
|
||||||
- float(min_width / 2.), float(min_width / 2.));
|
- float(min_width / 2.), float(min_width / 2.));
|
||||||
// the maximum thickness of our thin wall area is equal to the minimum thickness of a single loop
|
// the maximum thickness of our thin wall area is equal to the minimum thickness of a single loop
|
||||||
for (ExPolygon &ex : expp)
|
for (ExPolygon &ex : expp)
|
||||||
|
@ -514,7 +512,7 @@ void PerimeterGenerator::process()
|
||||||
and use zigzag). */
|
and use zigzag). */
|
||||||
//FIXME Vojtech: This grows by a rounded extrusion width, not by line spacing,
|
//FIXME Vojtech: This grows by a rounded extrusion width, not by line spacing,
|
||||||
// therefore it may cover the area, but no the volume.
|
// therefore it may cover the area, but no the volume.
|
||||||
last = diff_ex(to_polygons(last), gap_fill.polygons_covered_by_width(10.f));
|
last = diff_ex(last, gap_fill.polygons_covered_by_width(10.f));
|
||||||
this->gap_fill->append(std::move(gap_fill.entities));
|
this->gap_fill->append(std::move(gap_fill.entities));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ double Polygon::area() const
|
||||||
|
|
||||||
bool Polygon::is_counter_clockwise() const
|
bool Polygon::is_counter_clockwise() const
|
||||||
{
|
{
|
||||||
return ClipperLib::Orientation(Slic3rMultiPoint_to_ClipperPath(*this));
|
return ClipperLib::Orientation(this->points);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Polygon::is_clockwise() const
|
bool Polygon::is_clockwise() const
|
||||||
|
|
|
@ -222,6 +222,24 @@ inline Polylines to_polylines(Polygons &&polys)
|
||||||
return polylines;
|
return polylines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Polygons to_polygons(const std::vector<Points> &paths)
|
||||||
|
{
|
||||||
|
Polygons out;
|
||||||
|
out.reserve(paths.size());
|
||||||
|
for (const Points &path : paths)
|
||||||
|
out.emplace_back(path);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Polygons to_polygons(std::vector<Points> &&paths)
|
||||||
|
{
|
||||||
|
Polygons out;
|
||||||
|
out.reserve(paths.size());
|
||||||
|
for (const Points &path : paths)
|
||||||
|
out.emplace_back(std::move(path));
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
} // Slic3r
|
} // Slic3r
|
||||||
|
|
||||||
// start Boost
|
// start Boost
|
||||||
|
|
|
@ -124,6 +124,24 @@ inline Lines to_lines(const Polylines &polys)
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Polylines to_polylines(const std::vector<Points> &paths)
|
||||||
|
{
|
||||||
|
Polylines out;
|
||||||
|
out.reserve(paths.size());
|
||||||
|
for (const Points &path : paths)
|
||||||
|
out.emplace_back(path);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Polylines to_polylines(std::vector<Points> &&paths)
|
||||||
|
{
|
||||||
|
Polylines out;
|
||||||
|
out.reserve(paths.size());
|
||||||
|
for (const Points &path : paths)
|
||||||
|
out.emplace_back(std::move(path));
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
inline void polylines_append(Polylines &dst, const Polylines &src)
|
inline void polylines_append(Polylines &dst, const Polylines &src)
|
||||||
{
|
{
|
||||||
dst.insert(dst.end(), src.begin(), src.end());
|
dst.insert(dst.end(), src.begin(), src.end());
|
||||||
|
|
|
@ -186,7 +186,7 @@ void PrintObject::make_perimeters()
|
||||||
m_print->throw_if_canceled();
|
m_print->throw_if_canceled();
|
||||||
LayerRegion &layerm = *m_layers[layer_idx]->m_regions[region_id];
|
LayerRegion &layerm = *m_layers[layer_idx]->m_regions[region_id];
|
||||||
const LayerRegion &upper_layerm = *m_layers[layer_idx+1]->m_regions[region_id];
|
const LayerRegion &upper_layerm = *m_layers[layer_idx+1]->m_regions[region_id];
|
||||||
const Polygons upper_layerm_polygons = upper_layerm.slices;
|
const Polygons upper_layerm_polygons = to_polygons(upper_layerm.slices.surfaces);
|
||||||
// Filter upper layer polygons in intersection_ppl by their bounding boxes?
|
// Filter upper layer polygons in intersection_ppl by their bounding boxes?
|
||||||
// my $upper_layerm_poly_bboxes= [ map $_->bounding_box, @{$upper_layerm_polygons} ];
|
// my $upper_layerm_poly_bboxes= [ map $_->bounding_box, @{$upper_layerm_polygons} ];
|
||||||
const double total_loop_length = total_length(upper_layerm_polygons);
|
const double total_loop_length = total_length(upper_layerm_polygons);
|
||||||
|
@ -809,19 +809,14 @@ void PrintObject::detect_surfaces_type()
|
||||||
// collapse very narrow parts (using the safety offset in the diff is not enough)
|
// collapse very narrow parts (using the safety offset in the diff is not enough)
|
||||||
float offset = layerm->flow(frExternalPerimeter).scaled_width() / 10.f;
|
float offset = layerm->flow(frExternalPerimeter).scaled_width() / 10.f;
|
||||||
|
|
||||||
Polygons layerm_slices_surfaces = to_polygons(layerm->slices.surfaces);
|
|
||||||
|
|
||||||
// find top surfaces (difference between current surfaces
|
// find top surfaces (difference between current surfaces
|
||||||
// of current layer and upper one)
|
// of current layer and upper one)
|
||||||
Surfaces top;
|
Surfaces top;
|
||||||
if (upper_layer) {
|
if (upper_layer) {
|
||||||
Polygons upper_slices = interface_shells ?
|
ExPolygons upper_slices = interface_shells ?
|
||||||
to_polygons(upper_layer->m_regions[idx_region]->slices.surfaces) :
|
diff_ex(layerm->slices.surfaces, upper_layer->m_regions[idx_region]->slices.surfaces, true) :
|
||||||
to_polygons(upper_layer->lslices);
|
diff_ex(layerm->slices.surfaces, upper_layer->lslices, true);
|
||||||
surfaces_append(top,
|
surfaces_append(top, offset2_ex(upper_slices, -offset, offset), stTop);
|
||||||
//FIXME implement offset2_ex working over ExPolygons, that should be a bit more efficient than calling offset_ex twice.
|
|
||||||
offset_ex(offset_ex(diff_ex(layerm_slices_surfaces, upper_slices, true), -offset), offset),
|
|
||||||
stTop);
|
|
||||||
} else {
|
} else {
|
||||||
// if no upper layer, all surfaces of this one are solid
|
// if no upper layer, all surfaces of this one are solid
|
||||||
// we clone surfaces because we're going to clear the slices collection
|
// we clone surfaces because we're going to clear the slices collection
|
||||||
|
@ -839,14 +834,14 @@ void PrintObject::detect_surfaces_type()
|
||||||
to_polygons(lower_layer->get_region(idx_region)->slices.surfaces) :
|
to_polygons(lower_layer->get_region(idx_region)->slices.surfaces) :
|
||||||
to_polygons(lower_layer->slices);
|
to_polygons(lower_layer->slices);
|
||||||
surfaces_append(bottom,
|
surfaces_append(bottom,
|
||||||
offset2_ex(diff(layerm_slices_surfaces, lower_slices, true), -offset, offset),
|
offset2_ex(diff(layerm->slices.surfaces, lower_slices, true), -offset, offset),
|
||||||
surface_type_bottom_other);
|
surface_type_bottom_other);
|
||||||
#else
|
#else
|
||||||
// Any surface lying on the void is a true bottom bridge (an overhang)
|
// Any surface lying on the void is a true bottom bridge (an overhang)
|
||||||
surfaces_append(
|
surfaces_append(
|
||||||
bottom,
|
bottom,
|
||||||
offset2_ex(
|
offset2_ex(
|
||||||
diff(layerm_slices_surfaces, to_polygons(lower_layer->lslices), true),
|
diff_ex(layerm->slices.surfaces, lower_layer->lslices, true),
|
||||||
-offset, offset),
|
-offset, offset),
|
||||||
surface_type_bottom_other);
|
surface_type_bottom_other);
|
||||||
// if user requested internal shells, we need to identify surfaces
|
// if user requested internal shells, we need to identify surfaces
|
||||||
|
@ -857,10 +852,10 @@ void PrintObject::detect_surfaces_type()
|
||||||
surfaces_append(
|
surfaces_append(
|
||||||
bottom,
|
bottom,
|
||||||
offset2_ex(
|
offset2_ex(
|
||||||
diff(
|
diff_ex(
|
||||||
intersection(layerm_slices_surfaces, to_polygons(lower_layer->lslices)), // supported
|
intersection(layerm->slices.surfaces, lower_layer->lslices), // supported
|
||||||
to_polygons(lower_layer->m_regions[idx_region]->slices.surfaces),
|
lower_layer->m_regions[idx_region]->slices.surfaces,
|
||||||
true),
|
true),
|
||||||
-offset, offset),
|
-offset, offset),
|
||||||
stBottom);
|
stBottom);
|
||||||
}
|
}
|
||||||
|
@ -883,7 +878,7 @@ void PrintObject::detect_surfaces_type()
|
||||||
Polygons top_polygons = to_polygons(std::move(top));
|
Polygons top_polygons = to_polygons(std::move(top));
|
||||||
top.clear();
|
top.clear();
|
||||||
surfaces_append(top,
|
surfaces_append(top,
|
||||||
diff_ex(top_polygons, to_polygons(bottom), false),
|
diff_ex(top_polygons, bottom, false),
|
||||||
stTop);
|
stTop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -900,15 +895,18 @@ void PrintObject::detect_surfaces_type()
|
||||||
|
|
||||||
// save surfaces to layer
|
// save surfaces to layer
|
||||||
Surfaces &surfaces_out = interface_shells ? surfaces_new[idx_layer] : layerm->slices.surfaces;
|
Surfaces &surfaces_out = interface_shells ? surfaces_new[idx_layer] : layerm->slices.surfaces;
|
||||||
surfaces_out.clear();
|
Surfaces surfaces_backup;
|
||||||
|
if (! interface_shells) {
|
||||||
|
surfaces_backup = std::move(surfaces_out);
|
||||||
|
surfaces_out.clear();
|
||||||
|
}
|
||||||
|
const Surfaces &surfaces_prev = interface_shells ? layerm->slices.surfaces : surfaces_backup;
|
||||||
|
|
||||||
// find internal surfaces (difference between top/bottom surfaces and others)
|
// find internal surfaces (difference between top/bottom surfaces and others)
|
||||||
{
|
{
|
||||||
Polygons topbottom = to_polygons(top);
|
Polygons topbottom = to_polygons(top);
|
||||||
polygons_append(topbottom, to_polygons(bottom));
|
polygons_append(topbottom, to_polygons(bottom));
|
||||||
surfaces_append(surfaces_out,
|
surfaces_append(surfaces_out, diff_ex(surfaces_prev, topbottom, false), stInternal);
|
||||||
diff_ex(layerm_slices_surfaces, topbottom, false),
|
|
||||||
stInternal);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
surfaces_append(surfaces_out, std::move(top));
|
surfaces_append(surfaces_out, std::move(top));
|
||||||
|
@ -1012,7 +1010,7 @@ void PrintObject::process_external_surfaces()
|
||||||
// Shrink the holes, let the layer above expand slightly inside the unsupported areas.
|
// Shrink the holes, let the layer above expand slightly inside the unsupported areas.
|
||||||
polygons_append(voids, offset(surface.expolygon, unsupported_width));
|
polygons_append(voids, offset(surface.expolygon, unsupported_width));
|
||||||
}
|
}
|
||||||
surfaces_covered[layer_idx] = diff(to_polygons(this->m_layers[layer_idx]->lslices), voids);
|
surfaces_covered[layer_idx] = diff(this->m_layers[layer_idx]->lslices, voids);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -1107,11 +1105,11 @@ void PrintObject::discover_vertical_shells()
|
||||||
LayerRegion &layerm = *layer.m_regions[idx_region];
|
LayerRegion &layerm = *layer.m_regions[idx_region];
|
||||||
float min_perimeter_infill_spacing = float(layerm.flow(frSolidInfill).scaled_spacing()) * 1.05f;
|
float min_perimeter_infill_spacing = float(layerm.flow(frSolidInfill).scaled_spacing()) * 1.05f;
|
||||||
// Top surfaces.
|
// Top surfaces.
|
||||||
append(cache.top_surfaces, offset(to_expolygons(layerm.slices.filter_by_type(stTop)), min_perimeter_infill_spacing));
|
append(cache.top_surfaces, offset(layerm.slices.filter_by_type(stTop), min_perimeter_infill_spacing));
|
||||||
append(cache.top_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_type(stTop)), min_perimeter_infill_spacing));
|
append(cache.top_surfaces, offset(layerm.fill_surfaces.filter_by_type(stTop), min_perimeter_infill_spacing));
|
||||||
// Bottom surfaces.
|
// Bottom surfaces.
|
||||||
append(cache.bottom_surfaces, offset(to_expolygons(layerm.slices.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing));
|
append(cache.bottom_surfaces, offset(layerm.slices.filter_by_types(surfaces_bottom, 2), min_perimeter_infill_spacing));
|
||||||
append(cache.bottom_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing));
|
append(cache.bottom_surfaces, offset(layerm.fill_surfaces.filter_by_types(surfaces_bottom, 2), min_perimeter_infill_spacing));
|
||||||
// Calculate the maximum perimeter offset as if the slice was extruded with a single extruder only.
|
// Calculate the maximum perimeter offset as if the slice was extruded with a single extruder only.
|
||||||
// First find the maxium number of perimeters per region slice.
|
// First find the maxium number of perimeters per region slice.
|
||||||
unsigned int perimeters = 0;
|
unsigned int perimeters = 0;
|
||||||
|
@ -1181,11 +1179,11 @@ void PrintObject::discover_vertical_shells()
|
||||||
float min_perimeter_infill_spacing = float(layerm.flow(frSolidInfill).scaled_spacing()) * 1.05f;
|
float min_perimeter_infill_spacing = float(layerm.flow(frSolidInfill).scaled_spacing()) * 1.05f;
|
||||||
// Top surfaces.
|
// Top surfaces.
|
||||||
auto &cache = cache_top_botom_regions[idx_layer];
|
auto &cache = cache_top_botom_regions[idx_layer];
|
||||||
cache.top_surfaces = offset(to_expolygons(layerm.slices.filter_by_type(stTop)), min_perimeter_infill_spacing);
|
cache.top_surfaces = offset(layerm.slices.filter_by_type(stTop), min_perimeter_infill_spacing);
|
||||||
append(cache.top_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_type(stTop)), min_perimeter_infill_spacing));
|
append(cache.top_surfaces, offset(layerm.fill_surfaces.filter_by_type(stTop), min_perimeter_infill_spacing));
|
||||||
// Bottom surfaces.
|
// Bottom surfaces.
|
||||||
cache.bottom_surfaces = offset(to_expolygons(layerm.slices.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing);
|
cache.bottom_surfaces = offset(layerm.slices.filter_by_types(surfaces_bottom, 2), min_perimeter_infill_spacing);
|
||||||
append(cache.bottom_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing));
|
append(cache.bottom_surfaces, offset(layerm.fill_surfaces.filter_by_types(surfaces_bottom, 2), min_perimeter_infill_spacing));
|
||||||
// Holes over all regions. Only collect them once, they are valid for all idx_region iterations.
|
// Holes over all regions. Only collect them once, they are valid for all idx_region iterations.
|
||||||
if (cache.holes.empty()) {
|
if (cache.holes.empty()) {
|
||||||
for (size_t idx_region = 0; idx_region < layer.regions().size(); ++ idx_region)
|
for (size_t idx_region = 0; idx_region < layer.regions().size(); ++ idx_region)
|
||||||
|
@ -1407,16 +1405,8 @@ void PrintObject::discover_vertical_shells()
|
||||||
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||||
|
|
||||||
// Trim the internal & internalvoid by the shell.
|
// Trim the internal & internalvoid by the shell.
|
||||||
Slic3r::ExPolygons new_internal = diff_ex(
|
Slic3r::ExPolygons new_internal = diff_ex(layerm->fill_surfaces.filter_by_type(stInternal), shell);
|
||||||
to_polygons(layerm->fill_surfaces.filter_by_type(stInternal)),
|
Slic3r::ExPolygons new_internal_void = diff_ex(layerm->fill_surfaces.filter_by_type(stInternalVoid), shell);
|
||||||
shell,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
Slic3r::ExPolygons new_internal_void = diff_ex(
|
|
||||||
to_polygons(layerm->fill_surfaces.filter_by_type(stInternalVoid)),
|
|
||||||
shell,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||||
{
|
{
|
||||||
|
@ -1521,8 +1511,8 @@ void PrintObject::bridge_over_infill()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// compute the remaning internal solid surfaces as difference
|
// compute the remaning internal solid surfaces as difference
|
||||||
ExPolygons not_to_bridge = diff_ex(internal_solid, to_polygons(to_bridge), true);
|
ExPolygons not_to_bridge = diff_ex(internal_solid, to_bridge, true);
|
||||||
to_bridge = intersection_ex(to_polygons(to_bridge), internal_solid, true);
|
to_bridge = intersection_ex(to_bridge, internal_solid, true);
|
||||||
// build the new collection of fill_surfaces
|
// build the new collection of fill_surfaces
|
||||||
layerm->fill_surfaces.remove_type(stInternalSolid);
|
layerm->fill_surfaces.remove_type(stInternalSolid);
|
||||||
for (ExPolygon &ex : to_bridge)
|
for (ExPolygon &ex : to_bridge)
|
||||||
|
@ -1875,7 +1865,7 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
||||||
slices = offset_ex(std::move(slices), delta);
|
slices = offset_ex(std::move(slices), delta);
|
||||||
if (! processed.empty())
|
if (! processed.empty())
|
||||||
// Trim by the slices of already processed regions.
|
// Trim by the slices of already processed regions.
|
||||||
slices = diff_ex(to_polygons(std::move(slices)), processed);
|
slices = diff_ex(slices, processed);
|
||||||
if (size_t(&sliced_volume - &sliced_volumes.front()) + 1 < sliced_volumes.size())
|
if (size_t(&sliced_volume - &sliced_volumes.front()) + 1 < sliced_volumes.size())
|
||||||
// Collect the already processed regions to trim the to be processed regions.
|
// Collect the already processed regions to trim the to be processed regions.
|
||||||
polygons_append(processed, slices);
|
polygons_append(processed, slices);
|
||||||
|
@ -1926,12 +1916,11 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
||||||
LayerRegion *other_layerm = layer->m_regions[other_region_id];
|
LayerRegion *other_layerm = layer->m_regions[other_region_id];
|
||||||
if (layerm == nullptr || other_layerm == nullptr || other_layerm->slices.empty() || expolygons_by_layer[layer_id].empty())
|
if (layerm == nullptr || other_layerm == nullptr || other_layerm->slices.empty() || expolygons_by_layer[layer_id].empty())
|
||||||
continue;
|
continue;
|
||||||
Polygons other_slices = to_polygons(other_layerm->slices);
|
ExPolygons my_parts = intersection_ex(other_layerm->slices.surfaces, expolygons_by_layer[layer_id]);
|
||||||
ExPolygons my_parts = intersection_ex(other_slices, to_polygons(expolygons_by_layer[layer_id]));
|
|
||||||
if (my_parts.empty())
|
if (my_parts.empty())
|
||||||
continue;
|
continue;
|
||||||
// Remove such parts from original region.
|
// Remove such parts from original region.
|
||||||
other_layerm->slices.set(diff_ex(other_slices, to_polygons(my_parts)), stInternal);
|
other_layerm->slices.set(diff_ex(other_layerm->slices.surfaces, my_parts), stInternal);
|
||||||
// Append new parts to our region.
|
// Append new parts to our region.
|
||||||
layerm->slices.append(std::move(my_parts), stInternal);
|
layerm->slices.append(std::move(my_parts), stInternal);
|
||||||
}
|
}
|
||||||
|
@ -2018,7 +2007,7 @@ end:
|
||||||
slices = offset_ex(std::move(slices), xy_compensation_scaled);
|
slices = offset_ex(std::move(slices), xy_compensation_scaled);
|
||||||
if (region_id > 0 && clip)
|
if (region_id > 0 && clip)
|
||||||
// Trim by the slices of already processed regions.
|
// Trim by the slices of already processed regions.
|
||||||
slices = diff_ex(to_polygons(std::move(slices)), processed);
|
slices = diff_ex(slices, processed);
|
||||||
if (clip && (region_id + 1 < layer->m_regions.size()))
|
if (clip && (region_id + 1 < layer->m_regions.size()))
|
||||||
// Collect the already processed regions to trim the to be processed regions.
|
// Collect the already processed regions to trim the to be processed regions.
|
||||||
polygons_append(processed, slices);
|
polygons_append(processed, slices);
|
||||||
|
@ -2650,10 +2639,7 @@ void PrintObject::discover_horizontal_shells()
|
||||||
neighbor_layerm->fill_surfaces.set(internal_solid, stInternalSolid);
|
neighbor_layerm->fill_surfaces.set(internal_solid, stInternalSolid);
|
||||||
// subtract intersections from layer surfaces to get resulting internal surfaces
|
// subtract intersections from layer surfaces to get resulting internal surfaces
|
||||||
Polygons polygons_internal = to_polygons(std::move(internal_solid));
|
Polygons polygons_internal = to_polygons(std::move(internal_solid));
|
||||||
ExPolygons internal = diff_ex(
|
ExPolygons internal = diff_ex(backup.filter_by_type(stInternal), polygons_internal, true);
|
||||||
to_polygons(backup.filter_by_type(stInternal)),
|
|
||||||
polygons_internal,
|
|
||||||
true);
|
|
||||||
// assign resulting internal surfaces to layer
|
// assign resulting internal surfaces to layer
|
||||||
neighbor_layerm->fill_surfaces.append(internal, stInternal);
|
neighbor_layerm->fill_surfaces.append(internal, stInternal);
|
||||||
polygons_append(polygons_internal, to_polygons(std::move(internal)));
|
polygons_append(polygons_internal, to_polygons(std::move(internal)));
|
||||||
|
@ -2664,7 +2650,7 @@ void PrintObject::discover_horizontal_shells()
|
||||||
backup.group(&top_bottom_groups);
|
backup.group(&top_bottom_groups);
|
||||||
for (SurfacesPtr &group : top_bottom_groups)
|
for (SurfacesPtr &group : top_bottom_groups)
|
||||||
neighbor_layerm->fill_surfaces.append(
|
neighbor_layerm->fill_surfaces.append(
|
||||||
diff_ex(to_polygons(group), polygons_internal),
|
diff_ex(group, polygons_internal),
|
||||||
// Use an existing surface as a template, it carries the bridge angle etc.
|
// Use an existing surface as a template, it carries the bridge angle etc.
|
||||||
*group.front());
|
*group.front());
|
||||||
}
|
}
|
||||||
|
@ -2743,10 +2729,7 @@ void PrintObject::combine_infill()
|
||||||
ExPolygons intersection = to_expolygons(layerms.front()->fill_surfaces.filter_by_type(stInternal));
|
ExPolygons intersection = to_expolygons(layerms.front()->fill_surfaces.filter_by_type(stInternal));
|
||||||
// Start looping from the second layer and intersect the current intersection with it.
|
// Start looping from the second layer and intersect the current intersection with it.
|
||||||
for (size_t i = 1; i < layerms.size(); ++ i)
|
for (size_t i = 1; i < layerms.size(); ++ i)
|
||||||
intersection = intersection_ex(
|
intersection = intersection_ex(layerms[i]->fill_surfaces.filter_by_type(stInternal), intersection);
|
||||||
to_polygons(intersection),
|
|
||||||
to_polygons(layerms[i]->fill_surfaces.filter_by_type(stInternal)),
|
|
||||||
false);
|
|
||||||
double area_threshold = layerms.front()->infill_area_threshold();
|
double area_threshold = layerms.front()->infill_area_threshold();
|
||||||
if (! intersection.empty() && area_threshold > 0.)
|
if (! intersection.empty() && area_threshold > 0.)
|
||||||
intersection.erase(std::remove_if(intersection.begin(), intersection.end(),
|
intersection.erase(std::remove_if(intersection.begin(), intersection.end(),
|
||||||
|
@ -2775,7 +2758,7 @@ void PrintObject::combine_infill()
|
||||||
for (ExPolygon &expoly : intersection)
|
for (ExPolygon &expoly : intersection)
|
||||||
polygons_append(intersection_with_clearance, offset(expoly, clearance_offset));
|
polygons_append(intersection_with_clearance, offset(expoly, clearance_offset));
|
||||||
for (LayerRegion *layerm : layerms) {
|
for (LayerRegion *layerm : layerms) {
|
||||||
Polygons internal = to_polygons(layerm->fill_surfaces.filter_by_type(stInternal));
|
Polygons internal = to_polygons(std::move(layerm->fill_surfaces.filter_by_type(stInternal)));
|
||||||
layerm->fill_surfaces.remove_type(stInternal);
|
layerm->fill_surfaces.remove_type(stInternal);
|
||||||
layerm->fill_surfaces.append(diff_ex(internal, intersection_with_clearance, false), stInternal);
|
layerm->fill_surfaces.append(diff_ex(internal, intersection_with_clearance, false), stInternal);
|
||||||
if (layerm == layerms.back()) {
|
if (layerm == layerms.back()) {
|
||||||
|
|
|
@ -42,9 +42,10 @@ Point ConcaveHull::centroid(const Points &pp)
|
||||||
|
|
||||||
// As it shows, the current offset_ex in ClipperUtils hangs if used in jtRound
|
// As it shows, the current offset_ex in ClipperUtils hangs if used in jtRound
|
||||||
// mode
|
// mode
|
||||||
static ClipperLib::Paths fast_offset(const ClipperLib::Paths &paths,
|
template<typename PolygonsProvider>
|
||||||
coord_t delta,
|
static ClipperLib::Paths fast_offset(PolygonsProvider &&paths,
|
||||||
ClipperLib::JoinType jointype)
|
coord_t delta,
|
||||||
|
ClipperLib::JoinType jointype)
|
||||||
{
|
{
|
||||||
using ClipperLib::ClipperOffset;
|
using ClipperLib::ClipperOffset;
|
||||||
using ClipperLib::etClosedPolygon;
|
using ClipperLib::etClosedPolygon;
|
||||||
|
@ -61,7 +62,7 @@ static ClipperLib::Paths fast_offset(const ClipperLib::Paths &paths,
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
offs.AddPaths(paths, jointype, etClosedPolygon);
|
offs.AddPaths(std::forward<PolygonsProvider>(paths), jointype, etClosedPolygon);
|
||||||
|
|
||||||
Paths result;
|
Paths result;
|
||||||
offs.Execute(result, static_cast<double>(delta));
|
offs.Execute(result, static_cast<double>(delta));
|
||||||
|
@ -157,11 +158,9 @@ ExPolygons ConcaveHull::to_expolygons() const
|
||||||
|
|
||||||
ExPolygons offset_waffle_style_ex(const ConcaveHull &hull, coord_t delta)
|
ExPolygons offset_waffle_style_ex(const ConcaveHull &hull, coord_t delta)
|
||||||
{
|
{
|
||||||
ClipperLib::Paths paths = Slic3rMultiPoints_to_ClipperPaths(hull.polygons());
|
ExPolygons ret = ClipperPaths_to_Slic3rExPolygons(
|
||||||
paths = fast_offset(paths, 2 * delta, ClipperLib::jtRound);
|
fast_offset(fast_offset(ClipperUtils::PolygonsProvider(hull.polygons()), 2 * delta, ClipperLib::jtRound), -delta, ClipperLib::jtRound));
|
||||||
paths = fast_offset(paths, -delta, ClipperLib::jtRound);
|
for (ExPolygon &p : ret) p.holes.clear();
|
||||||
ExPolygons ret = ClipperPaths_to_Slic3rExPolygons(paths);
|
|
||||||
for (ExPolygon &p : ret) p.holes = {};
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -179,10 +179,10 @@ PadSkeleton divide_blueprint(const ExPolygons &bp)
|
||||||
ret.outer.reserve(size_t(ptree.Total()));
|
ret.outer.reserve(size_t(ptree.Total()));
|
||||||
|
|
||||||
for (ClipperLib::PolyTree::PolyNode *node : ptree.Childs) {
|
for (ClipperLib::PolyTree::PolyNode *node : ptree.Childs) {
|
||||||
ExPolygon poly(ClipperPath_to_Slic3rPolygon(node->Contour));
|
ExPolygon poly;
|
||||||
|
poly.contour.points = std::move(node->Contour);
|
||||||
for (ClipperLib::PolyTree::PolyNode *child : node->Childs) {
|
for (ClipperLib::PolyTree::PolyNode *child : node->Childs) {
|
||||||
poly.holes.emplace_back(
|
poly.holes.emplace_back(std::move(child->Contour));
|
||||||
ClipperPath_to_Slic3rPolygon(child->Contour));
|
|
||||||
|
|
||||||
traverse_pt(child->Childs, &ret.inner);
|
traverse_pt(child->Childs, &ret.inner);
|
||||||
}
|
}
|
||||||
|
@ -342,18 +342,18 @@ public:
|
||||||
template<class...Args>
|
template<class...Args>
|
||||||
ExPolygon offset_contour_only(const ExPolygon &poly, coord_t delta, Args...args)
|
ExPolygon offset_contour_only(const ExPolygon &poly, coord_t delta, Args...args)
|
||||||
{
|
{
|
||||||
ExPolygons tmp = offset_ex(poly.contour, float(delta), args...);
|
Polygons tmp = offset(poly.contour, float(delta), args...);
|
||||||
|
|
||||||
if (tmp.empty()) return {};
|
if (tmp.empty()) return {};
|
||||||
|
|
||||||
Polygons holes = poly.holes;
|
Polygons holes = poly.holes;
|
||||||
for (auto &h : holes) h.reverse();
|
for (auto &h : holes) h.reverse();
|
||||||
|
|
||||||
tmp = diff_ex(to_polygons(tmp), holes);
|
ExPolygons tmp2 = diff_ex(tmp, holes);
|
||||||
|
|
||||||
if (tmp.empty()) return {};
|
if (tmp2.empty()) return {};
|
||||||
|
|
||||||
return tmp.front();
|
return std::move(tmp2.front());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool add_cavity(Contour3D &pad, ExPolygon &top_poly, const PadConfig3D &cfg,
|
bool add_cavity(Contour3D &pad, ExPolygon &top_poly, const PadConfig3D &cfg,
|
||||||
|
|
|
@ -179,9 +179,8 @@ static std::vector<SupportPointGenerator::MyLayer> make_layers(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (! top.islands_below.empty()) {
|
if (! top.islands_below.empty()) {
|
||||||
Polygons top_polygons = to_polygons(*top.polygon);
|
|
||||||
Polygons bottom_polygons = top.polygons_below();
|
Polygons bottom_polygons = top.polygons_below();
|
||||||
top.overhangs = diff_ex(top_polygons, bottom_polygons);
|
top.overhangs = diff_ex(*top.polygon, bottom_polygons);
|
||||||
if (! top.overhangs.empty()) {
|
if (! top.overhangs.empty()) {
|
||||||
|
|
||||||
// Produce 2 bands around the island, a safe band for dangling overhangs
|
// Produce 2 bands around the island, a safe band for dangling overhangs
|
||||||
|
@ -191,7 +190,7 @@ static std::vector<SupportPointGenerator::MyLayer> make_layers(
|
||||||
auto overh_mask = offset(bottom_polygons, slope_offset, ClipperLib::jtSquare);
|
auto overh_mask = offset(bottom_polygons, slope_offset, ClipperLib::jtSquare);
|
||||||
|
|
||||||
// Absolutely hopeless overhangs are those outside the unsafe band
|
// Absolutely hopeless overhangs are those outside the unsafe band
|
||||||
top.overhangs = diff_ex(top_polygons, overh_mask);
|
top.overhangs = diff_ex(*top.polygon, overh_mask);
|
||||||
|
|
||||||
// Now cut out the supported core from the safe band
|
// Now cut out the supported core from the safe band
|
||||||
// and cut the safe band from the unsafe band to get distinct
|
// and cut the safe band from the unsafe band to get distinct
|
||||||
|
@ -199,8 +198,8 @@ static std::vector<SupportPointGenerator::MyLayer> make_layers(
|
||||||
overh_mask = diff(overh_mask, dangl_mask);
|
overh_mask = diff(overh_mask, dangl_mask);
|
||||||
dangl_mask = diff(dangl_mask, bottom_polygons);
|
dangl_mask = diff(dangl_mask, bottom_polygons);
|
||||||
|
|
||||||
top.dangling_areas = intersection_ex(top_polygons, dangl_mask);
|
top.dangling_areas = intersection_ex(*top.polygon, dangl_mask);
|
||||||
top.overhangs_slopes = intersection_ex(top_polygons, overh_mask);
|
top.overhangs_slopes = intersection_ex(*top.polygon, overh_mask);
|
||||||
|
|
||||||
top.overhangs_area = 0.f;
|
top.overhangs_area = 0.f;
|
||||||
std::vector<std::pair<ExPolygon*, float>> expolys_with_areas;
|
std::vector<std::pair<ExPolygon*, float>> expolys_with_areas;
|
||||||
|
|
|
@ -90,7 +90,7 @@ public:
|
||||||
float overlap_area(const Structure &rhs) const {
|
float overlap_area(const Structure &rhs) const {
|
||||||
double out = 0.;
|
double out = 0.;
|
||||||
if (this->bbox.overlap(rhs.bbox)) {
|
if (this->bbox.overlap(rhs.bbox)) {
|
||||||
Polygons polys = intersection(to_polygons(*this->polygon), to_polygons(*rhs.polygon), false);
|
Polygons polys = intersection(*this->polygon, *rhs.polygon, false);
|
||||||
for (const Polygon &poly : polys)
|
for (const Polygon &poly : polys)
|
||||||
out += poly.area();
|
out += poly.area();
|
||||||
}
|
}
|
||||||
|
|
|
@ -815,7 +815,7 @@ public:
|
||||||
// Expanding, thus m_support_polygons are all inside islands.
|
// Expanding, thus m_support_polygons are all inside islands.
|
||||||
union_ex(*m_support_polygons) :
|
union_ex(*m_support_polygons) :
|
||||||
// Shrinking, thus m_support_polygons may be trimmed a tiny bit by islands.
|
// Shrinking, thus m_support_polygons may be trimmed a tiny bit by islands.
|
||||||
intersection_ex(*m_support_polygons, to_polygons(islands)));
|
intersection_ex(*m_support_polygons, islands));
|
||||||
|
|
||||||
std::vector<std::pair<Point,bool>> samples_inside;
|
std::vector<std::pair<Point,bool>> samples_inside;
|
||||||
for (ExPolygon &island : islands) {
|
for (ExPolygon &island : islands) {
|
||||||
|
@ -932,7 +932,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deserialization constructor
|
// Deserialization constructor
|
||||||
bool deserialize_(const std::string &path, int which = -1)
|
bool deserialize_(const std::string &path, int which = -1)
|
||||||
{
|
{
|
||||||
FILE *file = ::fopen(path.c_str(), "rb");
|
FILE *file = ::fopen(path.c_str(), "rb");
|
||||||
if (file == nullptr)
|
if (file == nullptr)
|
||||||
|
@ -961,7 +961,7 @@ public:
|
||||||
poly.points.emplace_back(Point(x * scale, y * scale));
|
poly.points.emplace_back(Point(x * scale, y * scale));
|
||||||
}
|
}
|
||||||
if (which == -1 || which == i)
|
if (which == -1 || which == i)
|
||||||
m_support_polygons_deserialized.emplace_back(std::move(poly));
|
m_support_polygons_deserialized.emplace_back(std::move(poly));
|
||||||
printf("Polygon %d, area: %lf\n", i, area(poly.points));
|
printf("Polygon %d, area: %lf\n", i, area(poly.points));
|
||||||
}
|
}
|
||||||
::fread(&n_polygons, 4, 1, file);
|
::fread(&n_polygons, 4, 1, file);
|
||||||
|
@ -984,14 +984,14 @@ public:
|
||||||
m_support_polygons_deserialized = simplify_polygons(m_support_polygons_deserialized, false);
|
m_support_polygons_deserialized = simplify_polygons(m_support_polygons_deserialized, false);
|
||||||
//m_support_polygons_deserialized = to_polygons(union_ex(m_support_polygons_deserialized, false));
|
//m_support_polygons_deserialized = to_polygons(union_ex(m_support_polygons_deserialized, false));
|
||||||
|
|
||||||
// Create an EdgeGrid, initialize it with projection, initialize signed distance field.
|
// Create an EdgeGrid, initialize it with projection, initialize signed distance field.
|
||||||
coord_t grid_resolution = coord_t(scale_(m_support_spacing));
|
coord_t grid_resolution = coord_t(scale_(m_support_spacing));
|
||||||
BoundingBox bbox = get_extents(*m_support_polygons);
|
BoundingBox bbox = get_extents(*m_support_polygons);
|
||||||
bbox.offset(20);
|
bbox.offset(20);
|
||||||
bbox.align_to_grid(grid_resolution);
|
bbox.align_to_grid(grid_resolution);
|
||||||
m_grid.set_bbox(bbox);
|
m_grid.set_bbox(bbox);
|
||||||
m_grid.create(*m_support_polygons, grid_resolution);
|
m_grid.create(*m_support_polygons, grid_resolution);
|
||||||
m_grid.calculate_sdf();
|
m_grid.calculate_sdf();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1285,7 +1285,7 @@ namespace SupportMaterialInternal {
|
||||||
// Is the straight perimeter segment supported at both sides?
|
// Is the straight perimeter segment supported at both sides?
|
||||||
Point pts[2] = { polyline.first_point(), polyline.last_point() };
|
Point pts[2] = { polyline.first_point(), polyline.last_point() };
|
||||||
bool supported[2] = { false, false };
|
bool supported[2] = { false, false };
|
||||||
for (size_t i = 0; i < lower_layer.lslices.size() && ! (supported[0] && supported[1]); ++ i)
|
for (size_t i = 0; i < lower_layer.lslices.size() && ! (supported[0] && supported[1]); ++ i)
|
||||||
for (int j = 0; j < 2; ++ j)
|
for (int j = 0; j < 2; ++ j)
|
||||||
if (! supported[j] && lower_layer.lslices_bboxes[i].contains(pts[j]) && lower_layer.lslices[i].contains(pts[j]))
|
if (! supported[j] && lower_layer.lslices_bboxes[i].contains(pts[j]) && lower_layer.lslices[i].contains(pts[j]))
|
||||||
supported[j] = true;
|
supported[j] = true;
|
||||||
|
@ -1437,7 +1437,7 @@ static inline std::tuple<Polygons, Polygons, Polygons, float> detect_overhangs(
|
||||||
0.5f * fw);
|
0.5f * fw);
|
||||||
// Overhang polygons for this layer and region.
|
// Overhang polygons for this layer and region.
|
||||||
Polygons diff_polygons;
|
Polygons diff_polygons;
|
||||||
Polygons layerm_polygons = to_polygons(layerm->slices);
|
Polygons layerm_polygons = to_polygons(layerm->slices.surfaces);
|
||||||
if (lower_layer_offset == 0.f) {
|
if (lower_layer_offset == 0.f) {
|
||||||
// Support everything.
|
// Support everything.
|
||||||
diff_polygons = diff(layerm_polygons, lower_layer_polygons);
|
diff_polygons = diff(layerm_polygons, lower_layer_polygons);
|
||||||
|
@ -1469,13 +1469,13 @@ static inline std::tuple<Polygons, Polygons, Polygons, float> detect_overhangs(
|
||||||
diff_polygons = diff(diff_polygons, annotations.buildplate_covered[layer_id]);
|
diff_polygons = diff(diff_polygons, annotations.buildplate_covered[layer_id]);
|
||||||
}
|
}
|
||||||
if (! diff_polygons.empty()) {
|
if (! diff_polygons.empty()) {
|
||||||
// Offset the support regions back to a full overhang, restrict them to the full overhang.
|
// Offset the support regions back to a full overhang, restrict them to the full overhang.
|
||||||
// This is done to increase size of the supporting columns below, as they are calculated by
|
// This is done to increase size of the supporting columns below, as they are calculated by
|
||||||
// propagating these contact surfaces downwards.
|
// propagating these contact surfaces downwards.
|
||||||
diff_polygons = diff(
|
diff_polygons = diff(
|
||||||
intersection(offset(diff_polygons, lower_layer_offset, SUPPORT_SURFACES_OFFSET_PARAMETERS), layerm_polygons),
|
intersection(offset(diff_polygons, lower_layer_offset, SUPPORT_SURFACES_OFFSET_PARAMETERS), layerm_polygons),
|
||||||
lower_layer_polygons);
|
lower_layer_polygons);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1489,7 +1489,7 @@ static inline std::tuple<Polygons, Polygons, Polygons, float> detect_overhangs(
|
||||||
// Subtracting them as they are may leave unwanted narrow
|
// Subtracting them as they are may leave unwanted narrow
|
||||||
// residues of diff_polygons that would then be supported.
|
// residues of diff_polygons that would then be supported.
|
||||||
diff_polygons = diff(diff_polygons,
|
diff_polygons = diff(diff_polygons,
|
||||||
offset(union_(to_polygons(std::move(annotations.blockers_layers[layer_id]))), float(1000.*SCALED_EPSILON)));
|
offset(union_(annotations.blockers_layers[layer_id]), float(1000.*SCALED_EPSILON)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SLIC3R_DEBUG
|
#ifdef SLIC3R_DEBUG
|
||||||
|
@ -1538,7 +1538,7 @@ static inline std::tuple<Polygons, Polygons, Polygons, float> detect_overhangs(
|
||||||
slices_margin.offset = slices_margin_offset;
|
slices_margin.offset = slices_margin_offset;
|
||||||
slices_margin.polygons = (slices_margin_offset == 0.f) ?
|
slices_margin.polygons = (slices_margin_offset == 0.f) ?
|
||||||
lower_layer_polygons :
|
lower_layer_polygons :
|
||||||
offset2(to_polygons(lower_layer.lslices), - no_interface_offset * 0.5f, slices_margin_offset + no_interface_offset * 0.5f, SUPPORT_SURFACES_OFFSET_PARAMETERS);
|
offset2(lower_layer.lslices, - no_interface_offset * 0.5f, slices_margin_offset + no_interface_offset * 0.5f, SUPPORT_SURFACES_OFFSET_PARAMETERS);
|
||||||
if (buildplate_only && ! annotations.buildplate_covered[layer_id].empty()) {
|
if (buildplate_only && ! annotations.buildplate_covered[layer_id].empty()) {
|
||||||
if (has_enforcer)
|
if (has_enforcer)
|
||||||
// Make a backup of trimming polygons before enforcing "on build plate only".
|
// Make a backup of trimming polygons before enforcing "on build plate only".
|
||||||
|
@ -1569,9 +1569,9 @@ static inline std::tuple<Polygons, Polygons, Polygons, float> detect_overhangs(
|
||||||
if (has_enforcer) {
|
if (has_enforcer) {
|
||||||
// Enforce supports (as if with 90 degrees of slope) for the regions covered by the enforcer meshes.
|
// Enforce supports (as if with 90 degrees of slope) for the regions covered by the enforcer meshes.
|
||||||
#ifdef SLIC3R_DEBUG
|
#ifdef SLIC3R_DEBUG
|
||||||
ExPolygons enforcers_united = union_ex(to_polygons(annotations.enforcers_layers[layer_id]), false);
|
ExPolygons enforcers_united = union_ex(annotations.enforcers_layers[layer_id]);
|
||||||
#endif // SLIC3R_DEBUG
|
#endif // SLIC3R_DEBUG
|
||||||
enforcer_polygons = diff(intersection(to_polygons(layer.lslices), to_polygons(std::move(annotations.enforcers_layers[layer_id]))),
|
enforcer_polygons = diff(intersection(layer.lslices, annotations.enforcers_layers[layer_id]),
|
||||||
// Inflate just a tiny bit to avoid intersection of the overhang areas with the object.
|
// Inflate just a tiny bit to avoid intersection of the overhang areas with the object.
|
||||||
offset(lower_layer_polygons, 0.05f * fw, SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
offset(lower_layer_polygons, 0.05f * fw, SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
||||||
#ifdef SLIC3R_DEBUG
|
#ifdef SLIC3R_DEBUG
|
||||||
|
@ -2772,8 +2772,7 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object(
|
||||||
break;
|
break;
|
||||||
some_region_overlaps = true;
|
some_region_overlaps = true;
|
||||||
polygons_append(polygons_trimming,
|
polygons_append(polygons_trimming,
|
||||||
offset(to_expolygons(region->fill_surfaces.filter_by_type(stBottomBridge)),
|
offset(region->fill_surfaces.filter_by_type(stBottomBridge), gap_xy_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
||||||
gap_xy_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
|
||||||
if (region->region()->config().overhangs.value)
|
if (region->region()->config().overhangs.value)
|
||||||
// Add bridging perimeters.
|
// Add bridging perimeters.
|
||||||
SupportMaterialInternal::collect_bridging_perimeter_areas(region->perimeters, gap_xy_scaled, polygons_trimming);
|
SupportMaterialInternal::collect_bridging_perimeter_areas(region->perimeters, gap_xy_scaled, polygons_trimming);
|
||||||
|
@ -3093,8 +3092,8 @@ static inline void fill_expolygon_generate_paths(
|
||||||
Polylines polylines;
|
Polylines polylines;
|
||||||
try {
|
try {
|
||||||
polylines = filler->fill_surface(&surface, fill_params);
|
polylines = filler->fill_surface(&surface, fill_params);
|
||||||
} catch (InfillFailedException &) {
|
} catch (InfillFailedException &) {
|
||||||
}
|
}
|
||||||
extrusion_entities_append_paths(
|
extrusion_entities_append_paths(
|
||||||
dst,
|
dst,
|
||||||
std::move(polylines),
|
std::move(polylines),
|
||||||
|
|
|
@ -90,7 +90,6 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator Polygons() const { return this->expolygon; }
|
|
||||||
double area() const { return this->expolygon.area(); }
|
double area() const { return this->expolygon.area(); }
|
||||||
bool empty() const { return expolygon.empty(); }
|
bool empty() const { return expolygon.empty(); }
|
||||||
void clear() { expolygon.clear(); }
|
void clear() { expolygon.clear(); }
|
||||||
|
@ -107,6 +106,16 @@ public:
|
||||||
typedef std::vector<Surface> Surfaces;
|
typedef std::vector<Surface> Surfaces;
|
||||||
typedef std::vector<Surface*> SurfacesPtr;
|
typedef std::vector<Surface*> SurfacesPtr;
|
||||||
|
|
||||||
|
inline Polygons to_polygons(const Surface &surface)
|
||||||
|
{
|
||||||
|
return to_polygons(surface.expolygon);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Polygons to_polygons(Surface &&surface)
|
||||||
|
{
|
||||||
|
return to_polygons(std::move(surface.expolygon));
|
||||||
|
}
|
||||||
|
|
||||||
inline Polygons to_polygons(const Surfaces &src)
|
inline Polygons to_polygons(const Surfaces &src)
|
||||||
{
|
{
|
||||||
size_t num = 0;
|
size_t num = 0;
|
||||||
|
|
|
@ -6,18 +6,7 @@
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
SurfaceCollection::operator Polygons() const
|
void SurfaceCollection::simplify(double tolerance)
|
||||||
{
|
|
||||||
return to_polygons(surfaces);
|
|
||||||
}
|
|
||||||
|
|
||||||
SurfaceCollection::operator ExPolygons() const
|
|
||||||
{
|
|
||||||
return to_expolygons(surfaces);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
SurfaceCollection::simplify(double tolerance)
|
|
||||||
{
|
{
|
||||||
Surfaces ss;
|
Surfaces ss;
|
||||||
for (Surfaces::const_iterator it_s = this->surfaces.begin(); it_s != this->surfaces.end(); ++it_s) {
|
for (Surfaces::const_iterator it_s = this->surfaces.begin(); it_s != this->surfaces.end(); ++it_s) {
|
||||||
|
@ -33,8 +22,7 @@ SurfaceCollection::simplify(double tolerance)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* group surfaces by common properties */
|
/* group surfaces by common properties */
|
||||||
void
|
void SurfaceCollection::group(std::vector<SurfacesPtr> *retval)
|
||||||
SurfaceCollection::group(std::vector<SurfacesPtr> *retval)
|
|
||||||
{
|
{
|
||||||
for (Surfaces::iterator it = this->surfaces.begin(); it != this->surfaces.end(); ++it) {
|
for (Surfaces::iterator it = this->surfaces.begin(); it != this->surfaces.end(); ++it) {
|
||||||
// find a group with the same properties
|
// find a group with the same properties
|
||||||
|
@ -54,8 +42,7 @@ SurfaceCollection::group(std::vector<SurfacesPtr> *retval)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SurfacesPtr
|
SurfacesPtr SurfaceCollection::filter_by_type(const SurfaceType type)
|
||||||
SurfaceCollection::filter_by_type(const SurfaceType type)
|
|
||||||
{
|
{
|
||||||
SurfacesPtr ss;
|
SurfacesPtr ss;
|
||||||
for (Surfaces::iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) {
|
for (Surfaces::iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) {
|
||||||
|
@ -64,8 +51,7 @@ SurfaceCollection::filter_by_type(const SurfaceType type)
|
||||||
return ss;
|
return ss;
|
||||||
}
|
}
|
||||||
|
|
||||||
SurfacesPtr
|
SurfacesPtr SurfaceCollection::filter_by_types(const SurfaceType *types, int ntypes)
|
||||||
SurfaceCollection::filter_by_types(const SurfaceType *types, int ntypes)
|
|
||||||
{
|
{
|
||||||
SurfacesPtr ss;
|
SurfacesPtr ss;
|
||||||
for (Surfaces::iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) {
|
for (Surfaces::iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) {
|
||||||
|
@ -79,8 +65,7 @@ SurfaceCollection::filter_by_types(const SurfaceType *types, int ntypes)
|
||||||
return ss;
|
return ss;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void SurfaceCollection::filter_by_type(SurfaceType type, Polygons* polygons)
|
||||||
SurfaceCollection::filter_by_type(SurfaceType type, Polygons* polygons)
|
|
||||||
{
|
{
|
||||||
for (Surfaces::iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) {
|
for (Surfaces::iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) {
|
||||||
if (surface->surface_type == type) {
|
if (surface->surface_type == type) {
|
||||||
|
@ -90,8 +75,7 @@ SurfaceCollection::filter_by_type(SurfaceType type, Polygons* polygons)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void SurfaceCollection::keep_type(const SurfaceType type)
|
||||||
SurfaceCollection::keep_type(const SurfaceType type)
|
|
||||||
{
|
{
|
||||||
size_t j = 0;
|
size_t j = 0;
|
||||||
for (size_t i = 0; i < surfaces.size(); ++ i) {
|
for (size_t i = 0; i < surfaces.size(); ++ i) {
|
||||||
|
@ -105,8 +89,7 @@ SurfaceCollection::keep_type(const SurfaceType type)
|
||||||
surfaces.erase(surfaces.begin() + j, surfaces.end());
|
surfaces.erase(surfaces.begin() + j, surfaces.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void SurfaceCollection::keep_types(const SurfaceType *types, int ntypes)
|
||||||
SurfaceCollection::keep_types(const SurfaceType *types, int ntypes)
|
|
||||||
{
|
{
|
||||||
size_t j = 0;
|
size_t j = 0;
|
||||||
for (size_t i = 0; i < surfaces.size(); ++ i) {
|
for (size_t i = 0; i < surfaces.size(); ++ i) {
|
||||||
|
@ -127,8 +110,7 @@ SurfaceCollection::keep_types(const SurfaceType *types, int ntypes)
|
||||||
surfaces.erase(surfaces.begin() + j, surfaces.end());
|
surfaces.erase(surfaces.begin() + j, surfaces.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void SurfaceCollection::remove_type(const SurfaceType type)
|
||||||
SurfaceCollection::remove_type(const SurfaceType type)
|
|
||||||
{
|
{
|
||||||
size_t j = 0;
|
size_t j = 0;
|
||||||
for (size_t i = 0; i < surfaces.size(); ++ i) {
|
for (size_t i = 0; i < surfaces.size(); ++ i) {
|
||||||
|
@ -142,8 +124,7 @@ SurfaceCollection::remove_type(const SurfaceType type)
|
||||||
surfaces.erase(surfaces.begin() + j, surfaces.end());
|
surfaces.erase(surfaces.begin() + j, surfaces.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void SurfaceCollection::remove_types(const SurfaceType *types, int ntypes)
|
||||||
SurfaceCollection::remove_types(const SurfaceType *types, int ntypes)
|
|
||||||
{
|
{
|
||||||
size_t j = 0;
|
size_t j = 0;
|
||||||
for (size_t i = 0; i < surfaces.size(); ++ i) {
|
for (size_t i = 0; i < surfaces.size(); ++ i) {
|
||||||
|
|
|
@ -12,11 +12,10 @@ class SurfaceCollection
|
||||||
public:
|
public:
|
||||||
Surfaces surfaces;
|
Surfaces surfaces;
|
||||||
|
|
||||||
SurfaceCollection() {};
|
SurfaceCollection() = default;
|
||||||
SurfaceCollection(const Surfaces &surfaces) : surfaces(surfaces) {};
|
SurfaceCollection(const Surfaces& surfaces) : surfaces(surfaces) {};
|
||||||
SurfaceCollection(Surfaces &&surfaces) : surfaces(std::move(surfaces)) {};
|
SurfaceCollection(Surfaces &&surfaces) : surfaces(std::move(surfaces)) {};
|
||||||
operator Polygons() const;
|
|
||||||
operator ExPolygons() const;
|
|
||||||
void simplify(double tolerance);
|
void simplify(double tolerance);
|
||||||
void group(std::vector<SurfacesPtr> *retval);
|
void group(std::vector<SurfacesPtr> *retval);
|
||||||
template <class T> bool any_internal_contains(const T &item) const {
|
template <class T> bool any_internal_contains(const T &item) const {
|
||||||
|
|
|
@ -1804,9 +1804,9 @@ void TriangleMeshSlicer::make_expolygons(const Polygons &loops, const float clos
|
||||||
|
|
||||||
// append to the supplied collection
|
// append to the supplied collection
|
||||||
if (safety_offset > 0)
|
if (safety_offset > 0)
|
||||||
expolygons_append(*slices, offset2_ex(union_ex(loops, false), +safety_offset, -safety_offset));
|
expolygons_append(*slices, offset2_ex(union_ex(loops), +safety_offset, -safety_offset));
|
||||||
else
|
else
|
||||||
expolygons_append(*slices, union_ex(loops, false));
|
expolygons_append(*slices, union_ex(loops));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriangleMeshSlicer::make_expolygons(std::vector<IntersectionLine> &lines, const float closing_radius, ExPolygons* slices) const
|
void TriangleMeshSlicer::make_expolygons(std::vector<IntersectionLine> &lines, const float closing_radius, ExPolygons* slices) const
|
||||||
|
|
|
@ -194,7 +194,7 @@ bool Bed3D::set_shape(const Pointfs& shape, const std::string& custom_texture, c
|
||||||
const BoundingBox& bed_bbox = poly.contour.bounding_box();
|
const BoundingBox& bed_bbox = poly.contour.bounding_box();
|
||||||
calc_gridlines(poly, bed_bbox);
|
calc_gridlines(poly, bed_bbox);
|
||||||
|
|
||||||
m_polygon = offset_ex(poly.contour, (float)bed_bbox.radius() * 1.7f, jtRound, scale_(0.5))[0].contour;
|
m_polygon = offset(poly.contour, (float)bed_bbox.radius() * 1.7f, jtRound, scale_(0.5))[0];
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
m_texture.reset();
|
m_texture.reset();
|
||||||
|
|
|
@ -394,9 +394,9 @@ use Slic3r::Test;
|
||||||
});
|
});
|
||||||
return scalar keys %z_with_bridges;
|
return scalar keys %z_with_bridges;
|
||||||
};
|
};
|
||||||
ok $test->(Slic3r::Test::init_print('V', config => $config)) == 1,
|
ok $test->(Slic3r::Test::init_print('V', config => $config)) == 2,
|
||||||
'no overhangs printed with bridge speed'; # except for the first internal solid layers above void
|
'no overhangs printed with bridge speed'; # except for the two internal solid layers above void
|
||||||
ok $test->(Slic3r::Test::init_print('V', config => $config, scale_xyz => [3,1,1])) > 1,
|
ok $test->(Slic3r::Test::init_print('V', config => $config, scale_xyz => [3,1,1])) > 2,
|
||||||
'overhangs printed with bridge speed';
|
'overhangs printed with bridge speed';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ SCENARIO("Various Clipper operations - xs/t/11_clipper.t", "[ClipperUtils]") {
|
||||||
THEN("offset matches") {
|
THEN("offset matches") {
|
||||||
REQUIRE(result == Polygons {
|
REQUIRE(result == Polygons {
|
||||||
{ { 205, 205 }, { 95, 205 }, { 95, 95 }, { 205, 95 }, },
|
{ { 205, 205 }, { 95, 205 }, { 95, 95 }, { 205, 95 }, },
|
||||||
{ { 145, 145 }, { 145, 155 }, { 155, 155 }, { 155, 145 } } });
|
{ { 155, 145 }, { 145, 145 }, { 145, 155 }, { 155, 155 } } });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WHEN("offset_ex") {
|
WHEN("offset_ex") {
|
||||||
|
@ -56,7 +56,7 @@ SCENARIO("Various Clipper operations - xs/t/11_clipper.t", "[ClipperUtils]") {
|
||||||
}
|
}
|
||||||
GIVEN("square and hole") {
|
GIVEN("square and hole") {
|
||||||
WHEN("diff_ex") {
|
WHEN("diff_ex") {
|
||||||
ExPolygons result = Slic3r::diff_ex({ square }, { hole_in_square });
|
ExPolygons result = Slic3r::diff_ex(Polygons{ square }, Polygons{ hole_in_square });
|
||||||
THEN("hole is created") {
|
THEN("hole is created") {
|
||||||
REQUIRE(result.size() == 1);
|
REQUIRE(result.size() == 1);
|
||||||
REQUIRE(square_with_hole.area() == result.front().area());
|
REQUIRE(square_with_hole.area() == result.front().area());
|
||||||
|
@ -77,7 +77,7 @@ SCENARIO("Various Clipper operations - xs/t/11_clipper.t", "[ClipperUtils]") {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WHEN("diff_pl") {
|
WHEN("diff_pl") {
|
||||||
Polylines result = Slic3r::diff_pl({ polyline }, { square, hole_in_square });
|
Polylines result = Slic3r::diff_pl({ polyline }, Polygons{ square, hole_in_square });
|
||||||
THEN("correct number of result lines") {
|
THEN("correct number of result lines") {
|
||||||
REQUIRE(result.size() == 3);
|
REQUIRE(result.size() == 3);
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,7 @@ SCENARIO("Various Clipper operations - t/clipper.t", "[ClipperUtils]") {
|
||||||
// CW oriented contour
|
// CW oriented contour
|
||||||
Slic3r::Polygon hole_in_square { { 14, 14 }, { 14, 16 }, { 16, 16 }, { 16, 14 } };
|
Slic3r::Polygon hole_in_square { { 14, 14 }, { 14, 16 }, { 16, 16 }, { 16, 14 } };
|
||||||
WHEN("intersection_ex with another square") {
|
WHEN("intersection_ex with another square") {
|
||||||
ExPolygons intersection = Slic3r::intersection_ex({ square, hole_in_square }, { square2 });
|
ExPolygons intersection = Slic3r::intersection_ex(Polygons{ square, hole_in_square }, Polygons{ square2 });
|
||||||
THEN("intersection area matches (hole is preserved)") {
|
THEN("intersection area matches (hole is preserved)") {
|
||||||
ExPolygon match({ { 20, 18 }, { 10, 18 }, { 10, 12 }, { 20, 12 } },
|
ExPolygon match({ { 20, 18 }, { 10, 18 }, { 10, 12 }, { 20, 12 } },
|
||||||
{ { 14, 16 }, { 16, 16 }, { 16, 14 }, { 14, 14 } });
|
{ { 14, 16 }, { 16, 16 }, { 16, 14 }, { 14, 14 } });
|
||||||
|
@ -203,7 +203,7 @@ SCENARIO("Various Clipper operations - t/clipper.t", "[ClipperUtils]") {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WHEN("diff_ex with another square") {
|
WHEN("diff_ex with another square") {
|
||||||
ExPolygons diff = Slic3r::diff_ex({ square, square2 }, { hole });
|
ExPolygons diff = Slic3r::diff_ex(Polygons{ square, square2 }, Polygons{ hole });
|
||||||
THEN("difference of a cw from two ccw is a contour with one hole") {
|
THEN("difference of a cw from two ccw is a contour with one hole") {
|
||||||
REQUIRE(diff.size() == 1);
|
REQUIRE(diff.size() == 1);
|
||||||
REQUIRE(diff.front().area() == Approx(ExPolygon({ {40, 40}, {0, 40}, {0, 0}, {40, 0} }, { {15, 25}, {25, 25}, {25, 15}, {15, 15} }).area()));
|
REQUIRE(diff.front().area() == Approx(ExPolygon({ {40, 40}, {0, 40}, {0, 0}, {40, 0} }, { {15, 25}, {25, 25}, {25, 15}, {15, 15} }).area()));
|
||||||
|
@ -214,7 +214,7 @@ SCENARIO("Various Clipper operations - t/clipper.t", "[ClipperUtils]") {
|
||||||
Slic3r::Polygon square { { 10, 10 }, { 20, 10 }, { 20, 20 }, { 10, 20 } };
|
Slic3r::Polygon square { { 10, 10 }, { 20, 10 }, { 20, 20 }, { 10, 20 } };
|
||||||
Slic3r::Polyline square_pl = square.split_at_first_point();
|
Slic3r::Polyline square_pl = square.split_at_first_point();
|
||||||
WHEN("no-op diff_pl") {
|
WHEN("no-op diff_pl") {
|
||||||
Slic3r::Polylines res = Slic3r::diff_pl({ square_pl }, {});
|
Slic3r::Polylines res = Slic3r::diff_pl({ square_pl }, Polygons{});
|
||||||
THEN("returns the right number of polylines") {
|
THEN("returns the right number of polylines") {
|
||||||
REQUIRE(res.size() == 1);
|
REQUIRE(res.size() == 1);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue