Further rework of ClipperUtils: Replaced many to_polygons() /
to_expolygons() calls with templated ClipperUtils variants to avoid memory allocation and copying.
This commit is contained in:
parent
9fbba855ef
commit
09a80d954c
@ -244,12 +244,16 @@ static void get_trapezoids2(const ExPolygon &expoly, Polygons* polygons)
|
||||
std::sort(xx.begin(), xx.end());
|
||||
|
||||
// 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) {
|
||||
coord_t next_x = *(x + 1);
|
||||
if (*x != next_x)
|
||||
if (*x != next_x) {
|
||||
// intersect with rectangle
|
||||
// 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);
|
||||
// Intersect trapezoids with actual bridge area to remove extra margins and append it to result.
|
||||
polygons_rotate(covered, -(PI/2.0 - angle));
|
||||
covered = intersection(covered, to_polygons(this->expolygons));
|
||||
covered = intersection(this->expolygons, covered);
|
||||
#if 0
|
||||
{
|
||||
my @lines = map @{$_->lines}, @$trapezoids;
|
||||
|
@ -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)
|
||||
|
@ -188,77 +188,9 @@ Slic3r::ExPolygons offset_ex(const Slic3r::Polygons &polygons, const float delta
|
||||
{ return ClipperPaths_to_Slic3rExPolygons(_offset(ClipperUtils::PolygonsProvider(polygons), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); }
|
||||
#endif // CLIPPERUTILS_UNSAFE_OFFSET
|
||||
|
||||
// This is a safe variant of the polygon offset, tailored for a single ExPolygon:
|
||||
// a single polygon with multiple non-overlapping holes.
|
||||
// Each contour and hole is offsetted separately, then the holes are subtracted from the outer contours.
|
||||
ClipperLib::Paths _offset(const Slic3r::ExPolygon &expolygon, const float delta,
|
||||
ClipperLib::JoinType joinType, double miterLimit)
|
||||
// returns number of expolygons collected (0 or 1).
|
||||
static int offset_expolygon_inner(const Slic3r::ExPolygon &expoly, const float delta, ClipperLib::JoinType joinType, double miterLimit, ClipperLib::Paths &out)
|
||||
{
|
||||
// printf("new ExPolygon offset\n");
|
||||
// 1) Offset the outer contour.
|
||||
float delta_scaled = delta;
|
||||
ClipperLib::Paths contours;
|
||||
{
|
||||
ClipperLib::ClipperOffset co;
|
||||
if (joinType == jtRound)
|
||||
co.ArcTolerance = miterLimit;
|
||||
else
|
||||
co.MiterLimit = miterLimit;
|
||||
co.ShortestEdgeLength = double(std::abs(delta_scaled * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR));
|
||||
co.AddPath(expolygon.contour.points, joinType, ClipperLib::etClosedPolygon);
|
||||
co.Execute(contours, delta_scaled);
|
||||
}
|
||||
|
||||
// 2) Offset the holes one by one, collect the results.
|
||||
ClipperLib::Paths holes;
|
||||
{
|
||||
holes.reserve(expolygon.holes.size());
|
||||
for (Polygons::const_iterator it_hole = expolygon.holes.begin(); it_hole != expolygon.holes.end(); ++ it_hole) {
|
||||
ClipperLib::ClipperOffset co;
|
||||
if (joinType == jtRound)
|
||||
co.ArcTolerance = miterLimit;
|
||||
else
|
||||
co.MiterLimit = miterLimit;
|
||||
co.ShortestEdgeLength = double(std::abs(delta_scaled * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR));
|
||||
co.AddPath(it_hole->points, joinType, ClipperLib::etClosedPolygon);
|
||||
ClipperLib::Paths out;
|
||||
// Execute reorients the contours so that the outer most contour has a positive area. Thus the output
|
||||
// contours will be CCW oriented even though the input paths are CW oriented.
|
||||
// Offset is applied after contour reorientation, thus the signum of the offset value is reversed.
|
||||
co.Execute(out, - delta_scaled);
|
||||
append(holes, std::move(out));
|
||||
}
|
||||
}
|
||||
|
||||
// 3) Subtract holes from the contours.
|
||||
ClipperLib::Paths output;
|
||||
if (holes.empty()) {
|
||||
output = std::move(contours);
|
||||
} else {
|
||||
ClipperLib::Clipper clipper;
|
||||
clipper.Clear();
|
||||
clipper.AddPaths(contours, ClipperLib::ptSubject, true);
|
||||
clipper.AddPaths(holes, ClipperLib::ptClip, true);
|
||||
clipper.Execute(ClipperLib::ctDifference, output, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
// This is a safe variant of the polygons offset, tailored for multiple ExPolygons.
|
||||
// It is required, that the input expolygons do not overlap and that the holes of each ExPolygon don't intersect with their respective outer contours.
|
||||
// Each ExPolygon is offsetted separately, then the offsetted ExPolygons are united.
|
||||
ClipperLib::Paths _offset(const Slic3r::ExPolygons &expolygons, const float delta,
|
||||
ClipperLib::JoinType joinType, double miterLimit)
|
||||
{
|
||||
float delta_scaled = delta;
|
||||
// Offsetted ExPolygons before they are united.
|
||||
ClipperLib::Paths contours_cummulative;
|
||||
contours_cummulative.reserve(expolygons.size());
|
||||
// How many non-empty offsetted expolygons were actually collected into contours_cummulative?
|
||||
// If only one, then there is no need to do a final union.
|
||||
size_t expolygons_collected = 0;
|
||||
for (const Slic3r::ExPolygon &expoly : expolygons) {
|
||||
// 1) Offset the outer contour.
|
||||
ClipperLib::Paths contours;
|
||||
{
|
||||
@ -267,18 +199,17 @@ ClipperLib::Paths _offset(const Slic3r::ExPolygons &expolygons, const float delt
|
||||
co.ArcTolerance = miterLimit;
|
||||
else
|
||||
co.MiterLimit = miterLimit;
|
||||
co.ShortestEdgeLength = double(std::abs(delta_scaled * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR));
|
||||
co.ShortestEdgeLength = double(std::abs(delta * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR));
|
||||
co.AddPath(expoly.contour.points, joinType, ClipperLib::etClosedPolygon);
|
||||
co.Execute(contours, delta_scaled);
|
||||
co.Execute(contours, delta);
|
||||
}
|
||||
if (contours.empty())
|
||||
// No need to try to offset the holes.
|
||||
continue;
|
||||
return 0;
|
||||
|
||||
if (expoly.holes.empty()) {
|
||||
// No need to subtract holes from the offsetted expolygon, we are done.
|
||||
append(contours_cummulative, std::move(contours));
|
||||
++ expolygons_collected;
|
||||
append(out, std::move(contours));
|
||||
} else {
|
||||
// 2) Offset the holes one by one, collect the offsetted holes.
|
||||
ClipperLib::Paths holes;
|
||||
@ -289,22 +220,21 @@ ClipperLib::Paths _offset(const Slic3r::ExPolygons &expolygons, const float delt
|
||||
co.ArcTolerance = miterLimit;
|
||||
else
|
||||
co.MiterLimit = miterLimit;
|
||||
co.ShortestEdgeLength = double(std::abs(delta_scaled * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR));
|
||||
co.ShortestEdgeLength = double(std::abs(delta * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR));
|
||||
co.AddPath(hole.points, joinType, ClipperLib::etClosedPolygon);
|
||||
ClipperLib::Paths out;
|
||||
ClipperLib::Paths out2;
|
||||
// Execute reorients the contours so that the outer most contour has a positive area. Thus the output
|
||||
// contours will be CCW oriented even though the input paths are CW oriented.
|
||||
// Offset is applied after contour reorientation, thus the signum of the offset value is reversed.
|
||||
co.Execute(out, - delta_scaled);
|
||||
append(holes, std::move(out));
|
||||
co.Execute(out2, - delta);
|
||||
append(holes, std::move(out2));
|
||||
}
|
||||
}
|
||||
|
||||
// 3) Subtract holes from the contours.
|
||||
if (holes.empty()) {
|
||||
// No hole remaining after an offset. Just copy the outer contour.
|
||||
append(contours_cummulative, std::move(contours));
|
||||
++ expolygons_collected;
|
||||
append(out, std::move(contours));
|
||||
} else if (delta < 0) {
|
||||
// Negative offset. There is a chance, that the offsetted hole intersects the outer contour.
|
||||
// Subtract the offsetted holes from the offsetted contours.
|
||||
@ -315,42 +245,83 @@ ClipperLib::Paths _offset(const Slic3r::ExPolygons &expolygons, const float delt
|
||||
ClipperLib::Paths output;
|
||||
clipper.Execute(ClipperLib::ctDifference, output, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
|
||||
if (! output.empty()) {
|
||||
append(contours_cummulative, std::move(output));
|
||||
++ expolygons_collected;
|
||||
append(out, std::move(output));
|
||||
} else {
|
||||
// The offsetted holes have eaten up the offsetted outer contour.
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
// Positive offset. As long as the Clipper offset does what one expects it to do, the offsetted hole will have a smaller
|
||||
// area than the original hole or even disappear, therefore there will be no new intersections.
|
||||
// Just collect the reversed holes.
|
||||
contours_cummulative.reserve(contours.size() + holes.size());
|
||||
append(contours_cummulative, std::move(contours));
|
||||
out.reserve(contours.size() + holes.size());
|
||||
append(out, std::move(contours));
|
||||
// Reverse the holes in place.
|
||||
for (size_t i = 0; i < holes.size(); ++ i)
|
||||
std::reverse(holes[i].begin(), holes[i].end());
|
||||
append(contours_cummulative, std::move(holes));
|
||||
++ expolygons_collected;
|
||||
}
|
||||
append(out, std::move(holes));
|
||||
}
|
||||
}
|
||||
|
||||
// 4) Unite the offsetted expolygons.
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int offset_expolygon_inner(const Slic3r::Surface &surface, const float delta, ClipperLib::JoinType joinType, double miterLimit, ClipperLib::Paths &out)
|
||||
{ return offset_expolygon_inner(surface.expolygon, delta, joinType, miterLimit, out); }
|
||||
static int offset_expolygon_inner(const Slic3r::Surface *surface, const float delta, ClipperLib::JoinType joinType, double miterLimit, ClipperLib::Paths &out)
|
||||
{ return offset_expolygon_inner(surface->expolygon, delta, joinType, miterLimit, out); }
|
||||
|
||||
ClipperLib::Paths _offset(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType, double miterLimit)
|
||||
{
|
||||
ClipperLib::Paths out;
|
||||
offset_expolygon_inner(expolygon, delta, joinType, miterLimit, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
// This is a safe variant of the polygons offset, tailored for multiple ExPolygons.
|
||||
// It is required, that the input expolygons do not overlap and that the holes of each ExPolygon don't intersect with their respective outer contours.
|
||||
// Each ExPolygon is offsetted separately, then the offsetted ExPolygons are united.
|
||||
template<typename ExPolygonVector>
|
||||
ClipperLib::Paths _offset(const ExPolygonVector &expolygons, const float delta, ClipperLib::JoinType joinType, double miterLimit)
|
||||
{
|
||||
// Offsetted ExPolygons before they are united.
|
||||
ClipperLib::Paths output;
|
||||
output.reserve(expolygons.size());
|
||||
// How many non-empty offsetted expolygons were actually collected into output?
|
||||
// If only one, then there is no need to do a final union.
|
||||
size_t expolygons_collected = 0;
|
||||
for (const auto &expoly : expolygons)
|
||||
expolygons_collected += offset_expolygon_inner(expoly, delta, joinType, miterLimit, output);
|
||||
|
||||
// 4) Unite the offsetted expolygons.
|
||||
if (expolygons_collected > 1 && delta > 0) {
|
||||
// There is a chance that the outwards offsetted expolygons may intersect. Perform a union.
|
||||
ClipperLib::Clipper clipper;
|
||||
clipper.Clear();
|
||||
clipper.AddPaths(contours_cummulative, ClipperLib::ptSubject, true);
|
||||
clipper.AddPaths(output, ClipperLib::ptSubject, true);
|
||||
clipper.Execute(ClipperLib::ctUnion, output, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
|
||||
} else {
|
||||
// Negative offset. The shrunk expolygons shall not mutually intersect. Just copy the output.
|
||||
output = std::move(contours_cummulative);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
Slic3r::Polygons offset(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType, double miterLimit)
|
||||
{ return to_polygons(_offset(expolygon, delta, joinType, miterLimit)); }
|
||||
Slic3r::Polygons offset(const Slic3r::ExPolygons &expolygons, const float delta, ClipperLib::JoinType joinType, double miterLimit)
|
||||
{ return to_polygons(_offset(expolygons, delta, joinType, miterLimit)); }
|
||||
Slic3r::Polygons offset(const Slic3r::Surfaces &surfaces, const float delta, ClipperLib::JoinType joinType, double miterLimit)
|
||||
{ return to_polygons(_offset(surfaces, delta, joinType, miterLimit)); }
|
||||
Slic3r::Polygons offset(const Slic3r::SurfacesPtr &surfaces, const float delta, ClipperLib::JoinType joinType, double miterLimit)
|
||||
{ return to_polygons(_offset(surfaces, delta, joinType, miterLimit)); }
|
||||
Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType, double miterLimit)
|
||||
{ return ClipperPaths_to_Slic3rExPolygons(_offset(expolygon, delta, joinType, miterLimit)); }
|
||||
Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygons &expolygons, const float delta, ClipperLib::JoinType joinType, double miterLimit)
|
||||
{ return ClipperPaths_to_Slic3rExPolygons(_offset(expolygons, delta, joinType, miterLimit)); }
|
||||
Slic3r::ExPolygons offset_ex(const Slic3r::Surfaces &surfaces, const float delta, ClipperLib::JoinType joinType, double miterLimit)
|
||||
{ return ClipperPaths_to_Slic3rExPolygons(_offset(surfaces, delta, joinType, miterLimit)); }
|
||||
|
||||
ClipperLib::Paths _offset2(const Polygons &polygons, const float delta1, const float delta2, const ClipperLib::JoinType joinType, const double miterLimit)
|
||||
{
|
||||
// prepare ClipperOffset object
|
||||
@ -389,16 +360,14 @@ ExPolygons offset2_ex(const Polygons &polygons, const float delta1, const float
|
||||
}
|
||||
|
||||
//FIXME Vojtech: This functon may likely be optimized to avoid some of the Slic3r to Clipper
|
||||
// conversions and unnecessary Clipper calls.
|
||||
ExPolygons offset2_ex(const ExPolygons &expolygons, const float delta1,
|
||||
const float delta2, ClipperLib::JoinType joinType, double miterLimit)
|
||||
// conversions and unnecessary Clipper calls. It is not that bad now as Clipper uses Slic3r's own Point / Polygon types directly.
|
||||
Polygons offset2(const ExPolygons &expolygons, const float delta1, const float delta2, ClipperLib::JoinType joinType, double miterLimit)
|
||||
{
|
||||
Polygons polys;
|
||||
for (const ExPolygon &expoly : expolygons)
|
||||
append(polys,
|
||||
offset(offset_ex(expoly, delta1, joinType, miterLimit),
|
||||
delta2, joinType, miterLimit));
|
||||
return union_ex(polys);
|
||||
return offset(offset_ex(expolygons, delta1, joinType, miterLimit), delta2, joinType, miterLimit);
|
||||
}
|
||||
ExPolygons offset2_ex(const ExPolygons &expolygons, const float delta1, const float delta2, ClipperLib::JoinType joinType, double miterLimit)
|
||||
{
|
||||
return offset_ex(offset_ex(expolygons, delta1, joinType, miterLimit), delta2, joinType, miterLimit);
|
||||
}
|
||||
|
||||
template<class TResult, class TSubj, class TClip>
|
||||
@ -483,12 +452,22 @@ static inline Polygons _clipper(ClipperLib::ClipType clipType, TSubj &&subject,
|
||||
|
||||
Slic3r::Polygons diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset)
|
||||
{ return _clipper(ClipperLib::ctDifference, ClipperUtils::PolygonsProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::Polygons diff(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset)
|
||||
{ return _clipper(ClipperLib::ctDifference, ClipperUtils::ExPolygonsProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::Polygons diff(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset)
|
||||
{ return _clipper(ClipperLib::ctDifference, ClipperUtils::ExPolygonsProvider(subject), ClipperUtils::ExPolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::Polygons intersection(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset)
|
||||
{ return _clipper(ClipperLib::ctIntersection, ClipperUtils::PolygonsProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::Polygons intersection(const Slic3r::ExPolygon &subject, const Slic3r::ExPolygon &clip, bool do_safety_offset)
|
||||
{ return _clipper(ClipperLib::ctIntersection, ClipperUtils::ExPolygonProvider(subject), ClipperUtils::ExPolygonProvider(clip), do_safety_offset); }
|
||||
Slic3r::Polygons intersection(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset)
|
||||
{ return _clipper(ClipperLib::ctIntersection, ClipperUtils::ExPolygonsProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::Polygons intersection(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset)
|
||||
{ return _clipper(ClipperLib::ctIntersection, ClipperUtils::ExPolygonsProvider(subject), ClipperUtils::ExPolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::Polygons intersection(const Slic3r::Surfaces &subject, const Slic3r::Polygons &clip, bool do_safety_offset)
|
||||
{ return _clipper(ClipperLib::ctIntersection, ClipperUtils::SurfacesProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::Polygons intersection(const Slic3r::Surfaces &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset)
|
||||
{ return _clipper(ClipperLib::ctIntersection, ClipperUtils::SurfacesProvider(subject), ClipperUtils::ExPolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::Polygons union_(const Slic3r::Polygons &subject, bool do_safety_offset)
|
||||
{ return _clipper(ClipperLib::ctUnion, ClipperUtils::PolygonsProvider(subject), ClipperUtils::EmptyPathsProvider(), do_safety_offset); }
|
||||
Slic3r::Polygons union_(const Slic3r::ExPolygons &subject, bool do_safety_offset)
|
||||
@ -502,12 +481,45 @@ static ExPolygons _clipper_ex(ClipperLib::ClipType clipType, TSubject &&subject,
|
||||
|
||||
Slic3r::ExPolygons diff_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset)
|
||||
{ return _clipper_ex(ClipperLib::ctDifference, ClipperUtils::PolygonsProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::ExPolygons diff_ex(const Slic3r::Polygons &subject, const Slic3r::Surfaces &clip, bool do_safety_offset)
|
||||
{ return _clipper_ex(ClipperLib::ctDifference, ClipperUtils::PolygonsProvider(subject), ClipperUtils::SurfacesProvider(clip), do_safety_offset); }
|
||||
Slic3r::ExPolygons diff_ex(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset)
|
||||
{ return _clipper_ex(ClipperLib::ctDifference, ClipperUtils::PolygonsProvider(subject), ClipperUtils::ExPolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::ExPolygons diff_ex(const Slic3r::ExPolygon &subject, const Slic3r::Polygons &clip, bool do_safety_offset)
|
||||
{ return _clipper_ex(ClipperLib::ctDifference, ClipperUtils::ExPolygonProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::ExPolygons diff_ex(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset)
|
||||
{ return _clipper_ex(ClipperLib::ctDifference, ClipperUtils::ExPolygonsProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::ExPolygons diff_ex(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset)
|
||||
{ return _clipper_ex(ClipperLib::ctDifference, ClipperUtils::ExPolygonsProvider(subject), ClipperUtils::ExPolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::ExPolygons diff_ex(const Slic3r::Surfaces &subject, const Slic3r::Polygons &clip, bool do_safety_offset)
|
||||
{ return _clipper_ex(ClipperLib::ctDifference, ClipperUtils::SurfacesProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::ExPolygons diff_ex(const Slic3r::Surfaces &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset)
|
||||
{ return _clipper_ex(ClipperLib::ctDifference, ClipperUtils::SurfacesProvider(subject), ClipperUtils::ExPolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::ExPolygons diff_ex(const Slic3r::ExPolygons &subject, const Slic3r::Surfaces &clip, bool do_safety_offset)
|
||||
{ return _clipper_ex(ClipperLib::ctDifference, ClipperUtils::ExPolygonsProvider(subject), ClipperUtils::SurfacesProvider(clip), do_safety_offset); }
|
||||
Slic3r::ExPolygons diff_ex(const Slic3r::Surfaces &subject, const Slic3r::Surfaces &clip, bool do_safety_offset)
|
||||
{ return _clipper_ex(ClipperLib::ctDifference, ClipperUtils::SurfacesProvider(subject), ClipperUtils::SurfacesProvider(clip), do_safety_offset); }
|
||||
Slic3r::ExPolygons diff_ex(const Slic3r::SurfacesPtr &subject, const Slic3r::Polygons &clip, bool do_safety_offset)
|
||||
{ return _clipper_ex(ClipperLib::ctDifference, ClipperUtils::SurfacesPtrProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
|
||||
|
||||
Slic3r::ExPolygons intersection_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset)
|
||||
{ return _clipper_ex(ClipperLib::ctIntersection, ClipperUtils::PolygonsProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::ExPolygons intersection_ex(const Slic3r::ExPolygon &subject, const Slic3r::Polygons &clip, bool do_safety_offset)
|
||||
{ return _clipper_ex(ClipperLib::ctIntersection, ClipperUtils::ExPolygonProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::ExPolygons intersection_ex(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset)
|
||||
{ return _clipper_ex(ClipperLib::ctIntersection, ClipperUtils::PolygonsProvider(subject), ClipperUtils::ExPolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::ExPolygons intersection_ex(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset)
|
||||
{ return _clipper_ex(ClipperLib::ctIntersection, ClipperUtils::ExPolygonsProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::ExPolygons intersection_ex(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset)
|
||||
{ return _clipper_ex(ClipperLib::ctIntersection, ClipperUtils::ExPolygonsProvider(subject), ClipperUtils::ExPolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::ExPolygons intersection_ex(const Slic3r::Surfaces &subject, const Slic3r::Polygons &clip, bool do_safety_offset)
|
||||
{ return _clipper_ex(ClipperLib::ctIntersection, ClipperUtils::SurfacesProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::ExPolygons intersection_ex(const Slic3r::Surfaces &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset)
|
||||
{ return _clipper_ex(ClipperLib::ctIntersection, ClipperUtils::SurfacesProvider(subject), ClipperUtils::ExPolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::ExPolygons intersection_ex(const Slic3r::Surfaces &subject, const Slic3r::Surfaces &clip, bool do_safety_offset)
|
||||
{ return _clipper_ex(ClipperLib::ctIntersection, ClipperUtils::SurfacesProvider(subject), ClipperUtils::SurfacesProvider(clip), do_safety_offset); }
|
||||
Slic3r::ExPolygons intersection_ex(const Slic3r::SurfacesPtr &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset)
|
||||
{ return _clipper_ex(ClipperLib::ctIntersection, ClipperUtils::SurfacesPtrProvider(subject), ClipperUtils::ExPolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject, bool do_safety_offset)
|
||||
{ return _clipper_ex(ClipperLib::ctUnion, ClipperUtils::PolygonsProvider(subject), ClipperUtils::EmptyPathsProvider(), do_safety_offset); }
|
||||
Slic3r::ExPolygons union_ex(const Slic3r::ExPolygons& subject)
|
||||
@ -515,67 +527,93 @@ Slic3r::ExPolygons union_ex(const Slic3r::ExPolygons& subject)
|
||||
Slic3r::ExPolygons union_ex(const Slic3r::Surfaces& subject)
|
||||
{ return PolyTreeToExPolygons(_clipper_do_polytree2(ClipperLib::ctUnion, ClipperUtils::SurfacesProvider(subject), ClipperUtils::EmptyPathsProvider(), ClipperLib::pftNonZero)); }
|
||||
|
||||
Polylines _clipper_pl(ClipperLib::ClipType clipType, const Polylines &subject, const Polygons &clip, bool do_safety_offset)
|
||||
template<typename PathsProvider1, typename PathsProvider2>
|
||||
Polylines _clipper_pl_open(ClipperLib::ClipType clipType, PathsProvider1 &&subject, PathsProvider2 &&clip, bool do_safety_offset)
|
||||
{
|
||||
ClipperLib::Clipper clipper;
|
||||
clipper.AddPaths(ClipperUtils::PolylinesProvider(subject), ClipperLib::ptSubject, false);
|
||||
clipper.AddPaths(std::forward<PathsProvider1>(subject), ClipperLib::ptSubject, false);
|
||||
if (do_safety_offset)
|
||||
clipper.AddPaths(safety_offset(ClipperUtils::PolygonsProvider(clip)), ClipperLib::ptClip, true);
|
||||
clipper.AddPaths(safety_offset(std::forward<PathsProvider2>(clip)), ClipperLib::ptClip, true);
|
||||
else
|
||||
clipper.AddPaths(ClipperUtils::PolygonsProvider(clip), ClipperLib::ptClip, true);
|
||||
clipper.AddPaths(std::forward<PathsProvider2>(clip), ClipperLib::ptClip, true);
|
||||
ClipperLib::PolyTree retval;
|
||||
clipper.Execute(clipType, retval, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
|
||||
return PolyTreeToPolylines(std::move(retval));
|
||||
}
|
||||
|
||||
Polylines _clipper_pl(ClipperLib::ClipType clipType, const Polygons &subject, const Polygons &clip, bool do_safety_offset)
|
||||
// If the split_at_first_point() call above happens to split the polygon inside the clipping area
|
||||
// we would get two consecutive polylines instead of a single one, so we go through them in order
|
||||
// to recombine continuous polylines.
|
||||
static void _clipper_pl_recombine(Polylines &polylines)
|
||||
{
|
||||
// transform input polygons into polylines
|
||||
Polylines polylines;
|
||||
polylines.reserve(subject.size());
|
||||
for (Polygons::const_iterator polygon = subject.begin(); polygon != subject.end(); ++polygon)
|
||||
polylines.emplace_back(polygon->operator Polyline()); // implicit call to split_at_first_point()
|
||||
|
||||
// perform clipping
|
||||
Polylines retval = _clipper_pl(clipType, polylines, clip, do_safety_offset);
|
||||
|
||||
/* If the split_at_first_point() call above happens to split the polygon inside the clipping area
|
||||
we would get two consecutive polylines instead of a single one, so we go through them in order
|
||||
to recombine continuous polylines. */
|
||||
for (size_t i = 0; i < retval.size(); ++i) {
|
||||
for (size_t j = i+1; j < retval.size(); ++j) {
|
||||
if (retval[i].points.back() == retval[j].points.front()) {
|
||||
for (size_t i = 0; i < polylines.size(); ++i) {
|
||||
for (size_t j = i+1; j < polylines.size(); ++j) {
|
||||
if (polylines[i].points.back() == polylines[j].points.front()) {
|
||||
/* If last point of i coincides with first point of j,
|
||||
append points of j to i and delete j */
|
||||
retval[i].points.insert(retval[i].points.end(), retval[j].points.begin()+1, retval[j].points.end());
|
||||
retval.erase(retval.begin() + j);
|
||||
polylines[i].points.insert(polylines[i].points.end(), polylines[j].points.begin()+1, polylines[j].points.end());
|
||||
polylines.erase(polylines.begin() + j);
|
||||
--j;
|
||||
} else if (retval[i].points.front() == retval[j].points.back()) {
|
||||
} else if (polylines[i].points.front() == polylines[j].points.back()) {
|
||||
/* If first point of i coincides with last point of j,
|
||||
prepend points of j to i and delete j */
|
||||
retval[i].points.insert(retval[i].points.begin(), retval[j].points.begin(), retval[j].points.end()-1);
|
||||
retval.erase(retval.begin() + j);
|
||||
polylines[i].points.insert(polylines[i].points.begin(), polylines[j].points.begin(), polylines[j].points.end()-1);
|
||||
polylines.erase(polylines.begin() + j);
|
||||
--j;
|
||||
} else if (retval[i].points.front() == retval[j].points.front()) {
|
||||
} else if (polylines[i].points.front() == polylines[j].points.front()) {
|
||||
/* Since Clipper does not preserve orientation of polylines,
|
||||
also check the case when first point of i coincides with first point of j. */
|
||||
retval[j].reverse();
|
||||
retval[i].points.insert(retval[i].points.begin(), retval[j].points.begin(), retval[j].points.end()-1);
|
||||
retval.erase(retval.begin() + j);
|
||||
polylines[j].reverse();
|
||||
polylines[i].points.insert(polylines[i].points.begin(), polylines[j].points.begin(), polylines[j].points.end()-1);
|
||||
polylines.erase(polylines.begin() + j);
|
||||
--j;
|
||||
} else if (retval[i].points.back() == retval[j].points.back()) {
|
||||
} else if (polylines[i].points.back() == polylines[j].points.back()) {
|
||||
/* Since Clipper does not preserve orientation of polylines,
|
||||
also check the case when last point of i coincides with last point of j. */
|
||||
retval[j].reverse();
|
||||
retval[i].points.insert(retval[i].points.end(), retval[j].points.begin()+1, retval[j].points.end());
|
||||
retval.erase(retval.begin() + j);
|
||||
polylines[j].reverse();
|
||||
polylines[i].points.insert(polylines[i].points.end(), polylines[j].points.begin()+1, polylines[j].points.end());
|
||||
polylines.erase(polylines.begin() + j);
|
||||
--j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename PathProvider1, typename PathProvider2>
|
||||
Polylines _clipper_pl_closed(ClipperLib::ClipType clipType, PathProvider1 &&subject, PathProvider2 &&clip, bool do_safety_offset)
|
||||
{
|
||||
// Transform input polygons into open paths.
|
||||
ClipperLib::Paths paths;
|
||||
paths.reserve(subject.size());
|
||||
for (const Points &poly : subject) {
|
||||
// Emplace polygon, duplicate the 1st point.
|
||||
paths.push_back({});
|
||||
ClipperLib::Path &path = paths.back();
|
||||
path.reserve(poly.size() + 1);
|
||||
path = poly;
|
||||
path.emplace_back(poly.front());
|
||||
}
|
||||
// perform clipping
|
||||
Polylines retval = _clipper_pl_open(clipType, paths, std::forward<PathProvider2>(clip), do_safety_offset);
|
||||
_clipper_pl_recombine(retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
Slic3r::Polylines diff_pl(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool do_safety_offset)
|
||||
{ return _clipper_pl_open(ClipperLib::ctDifference, ClipperUtils::PolylinesProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::Polylines diff_pl(const Slic3r::Polylines &subject, const Slic3r::ExPolygon &clip, bool do_safety_offset)
|
||||
{ return _clipper_pl_open(ClipperLib::ctDifference, ClipperUtils::PolylinesProvider(subject), ClipperUtils::ExPolygonProvider(clip), do_safety_offset); }
|
||||
Slic3r::Polylines diff_pl(const Slic3r::Polylines &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset)
|
||||
{ return _clipper_pl_open(ClipperLib::ctDifference, ClipperUtils::PolylinesProvider(subject), ClipperUtils::ExPolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::Polylines diff_pl(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset)
|
||||
{ return _clipper_pl_closed(ClipperLib::ctDifference, ClipperUtils::PolygonsProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool do_safety_offset)
|
||||
{ return _clipper_pl_open(ClipperLib::ctIntersection, ClipperUtils::PolylinesProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset)
|
||||
{ return _clipper_pl_open(ClipperLib::ctIntersection, ClipperUtils::PolylinesProvider(subject), ClipperUtils::ExPolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::Polylines intersection_pl(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset)
|
||||
{ return _clipper_pl_closed(ClipperLib::ctIntersection, ClipperUtils::PolygonsProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
|
||||
|
||||
Lines _clipper_ln(ClipperLib::ClipType clipType, const Lines &subject, const Polygons &clip, bool do_safety_offset)
|
||||
{
|
||||
// convert Lines to Polylines
|
||||
@ -585,7 +623,7 @@ Lines _clipper_ln(ClipperLib::ClipType clipType, const Lines &subject, const Pol
|
||||
polylines.emplace_back(Polyline(line.a, line.b));
|
||||
|
||||
// perform operation
|
||||
polylines = _clipper_pl(clipType, polylines, clip, do_safety_offset);
|
||||
polylines = _clipper_pl_open(clipType, ClipperUtils::PolylinesProvider(polylines), ClipperUtils::PolygonsProvider(clip), do_safety_offset);
|
||||
|
||||
// convert Polylines to Lines
|
||||
Lines retval;
|
||||
|
@ -212,6 +212,47 @@ namespace ClipperUtils {
|
||||
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;
|
||||
int 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);
|
||||
@ -226,58 +267,45 @@ Slic3r::Polygons offset(const Slic3r::Polygons &polygons, const float delta, Cli
|
||||
// offset Polylines
|
||||
Slic3r::Polygons offset(const Slic3r::Polyline &polyline, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtSquare, double miterLimit = 3);
|
||||
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);
|
||||
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
|
||||
ClipperLib::Paths _offset(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType, double miterLimit);
|
||||
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 to_polygons(_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 to_polygons(_offset(expolygons, delta, joinType, miterLimit)); }
|
||||
Slic3r::Polygons offset2(const Slic3r::ExPolygons &expolygons, const float delta1, const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
|
||||
Slic3r::ExPolygons offset2_ex(const Slic3r::ExPolygons &expolygons, const float delta1, const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
|
||||
|
||||
#ifdef CLIPPERUTILS_UNSAFE_OFFSET
|
||||
Slic3r::ExPolygons offset_ex(const Slic3r::Polygons &polygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
|
||||
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
|
||||
|
||||
inline Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
|
||||
{ return ClipperPaths_to_Slic3rExPolygons(_offset(expolygon, delta, joinType, miterLimit)); }
|
||||
inline Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygons &expolygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
|
||||
{ return ClipperPaths_to_Slic3rExPolygons(_offset(expolygons, delta, joinType, miterLimit)); }
|
||||
|
||||
#ifdef CLIPPERUTILS_UNSAFE_OFFSET
|
||||
ClipperLib::Paths _offset2(const Slic3r::Polygons &polygons, const float delta1,
|
||||
const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
|
||||
double miterLimit = 3);
|
||||
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
|
||||
|
||||
Slic3r::ExPolygons offset2_ex(const Slic3r::ExPolygons &expolygons, const float delta1,
|
||||
const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
|
||||
double miterLimit = 3);
|
||||
|
||||
Slic3r::Polylines _clipper_pl(ClipperLib::ClipType clipType, const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||
Slic3r::Polylines _clipper_pl(ClipperLib::ClipType clipType, const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||
Slic3r::Lines _clipper_ln(ClipperLib::ClipType clipType, const Slic3r::Lines &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||
|
||||
Slic3r::Polygons diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||
Slic3r::Polygons diff(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||
Slic3r::Polygons diff(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
|
||||
Slic3r::ExPolygons diff_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||
Slic3r::ExPolygons diff_ex(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
|
||||
Slic3r::ExPolygons diff_ex(const Slic3r::Polygons &subject, const Slic3r::Surfaces &clip, bool do_safety_offset = false);
|
||||
Slic3r::ExPolygons diff_ex(const Slic3r::Polygon &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
|
||||
Slic3r::ExPolygons diff_ex(const Slic3r::ExPolygon &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||
Slic3r::ExPolygons diff_ex(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
|
||||
Slic3r::ExPolygons diff_ex(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
|
||||
|
||||
inline Slic3r::Polylines diff_pl(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false)
|
||||
{
|
||||
return _clipper_pl(ClipperLib::ctDifference, subject, clip, do_safety_offset);
|
||||
}
|
||||
|
||||
inline Slic3r::Polylines diff_pl(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false)
|
||||
{
|
||||
return _clipper_pl(ClipperLib::ctDifference, subject, clip, do_safety_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);
|
||||
|
||||
inline Slic3r::Lines diff_ln(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false)
|
||||
{
|
||||
@ -285,19 +313,23 @@ inline Slic3r::Lines diff_ln(const Slic3r::Lines &subject, const Slic3r::Polygon
|
||||
}
|
||||
|
||||
Slic3r::Polygons intersection(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool do_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);
|
||||
|
||||
inline Slic3r::Polylines intersection_pl(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false)
|
||||
{
|
||||
return _clipper_pl(ClipperLib::ctIntersection, subject, clip, do_safety_offset);
|
||||
}
|
||||
|
||||
inline Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false)
|
||||
{
|
||||
return _clipper_pl(ClipperLib::ctIntersection, subject, clip, do_safety_offset);
|
||||
}
|
||||
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)
|
||||
{
|
||||
|
@ -14,12 +14,12 @@ namespace Slic3r {
|
||||
|
||||
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
|
||||
{
|
||||
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)
|
||||
|
@ -162,7 +162,7 @@ void Fill3DHoneycomb::_fill_surface_single(
|
||||
pl.translate(bb.min);
|
||||
|
||||
// clip pattern to boundaries, chain the clipped polylines
|
||||
polylines = intersection_pl(polylines, to_polygons(expolygon));
|
||||
polylines = intersection_pl(polylines, expolygon);
|
||||
|
||||
// connect lines if needed
|
||||
if (params.dont_connect() || polylines.size() <= 1)
|
||||
|
@ -1368,7 +1368,7 @@ void Filler::_fill_surface_single(
|
||||
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 }; });
|
||||
// Crop all polylines
|
||||
all_polylines = intersection_pl(std::move(all_polylines), to_polygons(expolygon));
|
||||
all_polylines = intersection_pl(std::move(all_polylines), expolygon);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -180,7 +180,7 @@ void FillGyroid::_fill_surface_single(
|
||||
for (Polyline &pl : polylines)
|
||||
pl.translate(bb.min);
|
||||
|
||||
polylines = intersection_pl(polylines, to_polygons(expolygon));
|
||||
polylines = intersection_pl(polylines, expolygon);
|
||||
|
||||
if (! polylines.empty()) {
|
||||
// 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)
|
||||
append(polylines_out, chain_polylines(std::move(all_polylines)));
|
||||
else
|
||||
|
@ -44,7 +44,7 @@ void FillPlanePath::_fill_surface_single(
|
||||
coord_t(floor(pt.x() * 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);
|
||||
polylines = intersection_pl(std::move(polylines), to_polygons(expolygon));
|
||||
polylines = intersection_pl(std::move(polylines), expolygon);
|
||||
Polylines chained;
|
||||
if (params.dont_connect() || params.density > 0.5 || polylines.size() <= 1)
|
||||
chained = chain_polylines(std::move(polylines));
|
||||
|
@ -39,11 +39,11 @@ void Layer::make_slices()
|
||||
ExPolygons slices;
|
||||
if (m_regions.size() == 1) {
|
||||
// optimization: if we only have one region, take its slices
|
||||
slices = m_regions.front()->slices;
|
||||
slices = to_expolygons(m_regions.front()->slices.surfaces);
|
||||
} else {
|
||||
Polygons slices_p;
|
||||
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);
|
||||
}
|
||||
|
||||
@ -105,7 +105,7 @@ ExPolygons Layer::merged(float offset_scaled) const
|
||||
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.
|
||||
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);
|
||||
if (offset_scaled2 != 0.f)
|
||||
@ -185,7 +185,7 @@ void Layer::make_perimeters()
|
||||
}
|
||||
// merge the surfaces assigned to each group
|
||||
for (std::pair<const unsigned short,Surfaces> &surfaces_with_extra_perimeters : slices)
|
||||
new_slices.append(offset_ex(to_expolygons(surfaces_with_extra_perimeters.second), ClipperSafetyOffset), 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
|
||||
@ -196,7 +196,7 @@ void Layer::make_perimeters()
|
||||
if (!fill_surfaces.surfaces.empty()) {
|
||||
for (LayerRegionPtrs::iterator l = layerms.begin(); l != layerms.end(); ++l) {
|
||||
// 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_surfaces.set(std::move(expp), fill_surfaces.surfaces.front());
|
||||
}
|
||||
|
@ -196,7 +196,7 @@ protected:
|
||||
// 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) :
|
||||
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)
|
||||
// so we're safe. This guarantees idempotence of prepare_infill() also in case
|
||||
// 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.
|
||||
std::vector<Polygons> polygons_by_surface;
|
||||
polygons_by_surface.assign(size_t(stCount), Polygons());
|
||||
std::vector<SurfacesPtr> by_surface;
|
||||
by_surface.assign(size_t(stCount), SurfacesPtr());
|
||||
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.
|
||||
this->fill_surfaces.surfaces.clear();
|
||||
for (size_t surface_type = 0; surface_type < size_t(stCount); ++ surface_type) {
|
||||
const Polygons &polygons = polygons_by_surface[surface_type];
|
||||
if (! polygons.empty())
|
||||
this->fill_surfaces.append(intersection_ex(polygons, fill_boundaries), SurfaceType(surface_type));
|
||||
const SurfacesPtr &this_surfaces = by_surface[surface_type];
|
||||
if (! this_surfaces.empty())
|
||||
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!";
|
||||
} else {
|
||||
// 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));
|
||||
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())
|
||||
continue;
|
||||
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) {
|
||||
Surface &s2 = top[j];
|
||||
if (! s2.empty() && surfaces_could_merge(s1, s2)) {
|
||||
polygons_append(polys, std::move(s2));
|
||||
polygons_append(polys, to_polygons(std::move(s2)));
|
||||
s2.clear();
|
||||
}
|
||||
}
|
||||
@ -351,11 +349,11 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
|
||||
if (s1.empty())
|
||||
continue;
|
||||
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) {
|
||||
Surface &s2 = internal[j];
|
||||
if (! s2.empty() && surfaces_could_merge(s1, s2)) {
|
||||
polygons_append(polys, std::move(s2));
|
||||
polygons_append(polys, to_polygons(std::move(s2)));
|
||||
s2.clear();
|
||||
}
|
||||
}
|
||||
@ -423,7 +421,7 @@ void LayerRegion::trim_surfaces(const Polygons &trimming_polygons)
|
||||
for (const Surface &surface : this->slices.surfaces)
|
||||
assert(surface.surface_type == stInternal);
|
||||
#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)
|
||||
@ -432,10 +430,9 @@ void LayerRegion::elephant_foot_compensation_step(const float elephant_foot_comp
|
||||
for (const Surface &surface : this->slices.surfaces)
|
||||
assert(surface.surface_type == stInternal);
|
||||
#endif /* NDEBUG */
|
||||
ExPolygons slices_expolygons = to_expolygons(std::move(this->slices.surfaces));
|
||||
Polygons slices_polygons = to_polygons(slices_expolygons);
|
||||
Polygons tmp = intersection(slices_polygons, trimming_polygons, false);
|
||||
append(tmp, diff(slices_polygons, offset(offset_ex(slices_expolygons, -elephant_foot_compensation_perimeter_step), elephant_foot_compensation_perimeter_step)));
|
||||
ExPolygons surfaces = to_expolygons(std::move(this->slices.surfaces));
|
||||
Polygons tmp = intersection(surfaces, trimming_polygons);
|
||||
append(tmp, diff(surfaces, offset(offset_ex(surfaces, -elephant_foot_compensation_perimeter_step), elephant_foot_compensation_perimeter_step)));
|
||||
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));
|
||||
ExPolygons expp = offset2_ex(
|
||||
// medial axis requires non-overlapping geometry
|
||||
diff_ex(to_polygons(last),
|
||||
offset(offsets, float(ext_perimeter_width / 2.)),
|
||||
true),
|
||||
diff_ex(last, offset(offsets, float(ext_perimeter_width / 2.)), true),
|
||||
- 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
|
||||
for (ExPolygon &ex : expp)
|
||||
@ -514,7 +512,7 @@ void PerimeterGenerator::process()
|
||||
and use zigzag). */
|
||||
//FIXME Vojtech: This grows by a rounded extrusion width, not by line spacing,
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ void PrintObject::make_perimeters()
|
||||
m_print->throw_if_canceled();
|
||||
LayerRegion &layerm = *m_layers[layer_idx]->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?
|
||||
// my $upper_layerm_poly_bboxes= [ map $_->bounding_box, @{$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)
|
||||
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
|
||||
// of current layer and upper one)
|
||||
Surfaces top;
|
||||
if (upper_layer) {
|
||||
Polygons upper_slices = interface_shells ?
|
||||
to_polygons(upper_layer->m_regions[idx_region]->slices.surfaces) :
|
||||
to_polygons(upper_layer->lslices);
|
||||
surfaces_append(top,
|
||||
//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);
|
||||
ExPolygons upper_slices = interface_shells ?
|
||||
diff_ex(layerm->slices.surfaces, upper_layer->m_regions[idx_region]->slices.surfaces, true) :
|
||||
diff_ex(layerm->slices.surfaces, upper_layer->lslices, true);
|
||||
surfaces_append(top, offset2_ex(upper_slices, -offset, offset), stTop);
|
||||
} else {
|
||||
// if no upper layer, all surfaces of this one are solid
|
||||
// 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->slices);
|
||||
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);
|
||||
#else
|
||||
// Any surface lying on the void is a true bottom bridge (an overhang)
|
||||
surfaces_append(
|
||||
bottom,
|
||||
offset2_ex(
|
||||
diff(layerm_slices_surfaces, to_polygons(lower_layer->lslices), true),
|
||||
diff_ex(layerm->slices.surfaces, lower_layer->lslices, true),
|
||||
-offset, offset),
|
||||
surface_type_bottom_other);
|
||||
// if user requested internal shells, we need to identify surfaces
|
||||
@ -857,9 +852,9 @@ void PrintObject::detect_surfaces_type()
|
||||
surfaces_append(
|
||||
bottom,
|
||||
offset2_ex(
|
||||
diff(
|
||||
intersection(layerm_slices_surfaces, to_polygons(lower_layer->lslices)), // supported
|
||||
to_polygons(lower_layer->m_regions[idx_region]->slices.surfaces),
|
||||
diff_ex(
|
||||
intersection(layerm->slices.surfaces, lower_layer->lslices), // supported
|
||||
lower_layer->m_regions[idx_region]->slices.surfaces,
|
||||
true),
|
||||
-offset, offset),
|
||||
stBottom);
|
||||
@ -883,7 +878,7 @@ void PrintObject::detect_surfaces_type()
|
||||
Polygons top_polygons = to_polygons(std::move(top));
|
||||
top.clear();
|
||||
surfaces_append(top,
|
||||
diff_ex(top_polygons, to_polygons(bottom), false),
|
||||
diff_ex(top_polygons, bottom, false),
|
||||
stTop);
|
||||
}
|
||||
|
||||
@ -900,15 +895,18 @@ void PrintObject::detect_surfaces_type()
|
||||
|
||||
// save surfaces to layer
|
||||
Surfaces &surfaces_out = interface_shells ? surfaces_new[idx_layer] : layerm->slices.surfaces;
|
||||
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)
|
||||
{
|
||||
Polygons topbottom = to_polygons(top);
|
||||
polygons_append(topbottom, to_polygons(bottom));
|
||||
surfaces_append(surfaces_out,
|
||||
diff_ex(layerm_slices_surfaces, topbottom, false),
|
||||
stInternal);
|
||||
surfaces_append(surfaces_out, diff_ex(surfaces_prev, topbottom, false), stInternal);
|
||||
}
|
||||
|
||||
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.
|
||||
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];
|
||||
float min_perimeter_infill_spacing = float(layerm.flow(frSolidInfill).scaled_spacing()) * 1.05f;
|
||||
// Top surfaces.
|
||||
append(cache.top_surfaces, offset(to_expolygons(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.slices.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.
|
||||
append(cache.bottom_surfaces, offset(to_expolygons(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.slices.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.
|
||||
// First find the maxium number of perimeters per region slice.
|
||||
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;
|
||||
// Top surfaces.
|
||||
auto &cache = cache_top_botom_regions[idx_layer];
|
||||
cache.top_surfaces = offset(to_expolygons(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));
|
||||
cache.top_surfaces = offset(layerm.slices.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.
|
||||
cache.bottom_surfaces = offset(to_expolygons(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));
|
||||
cache.bottom_surfaces = offset(layerm.slices.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.
|
||||
if (cache.holes.empty()) {
|
||||
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 */
|
||||
|
||||
// Trim the internal & internalvoid by the shell.
|
||||
Slic3r::ExPolygons new_internal = diff_ex(
|
||||
to_polygons(layerm->fill_surfaces.filter_by_type(stInternal)),
|
||||
shell,
|
||||
false
|
||||
);
|
||||
Slic3r::ExPolygons new_internal_void = diff_ex(
|
||||
to_polygons(layerm->fill_surfaces.filter_by_type(stInternalVoid)),
|
||||
shell,
|
||||
false
|
||||
);
|
||||
Slic3r::ExPolygons new_internal = diff_ex(layerm->fill_surfaces.filter_by_type(stInternal), shell);
|
||||
Slic3r::ExPolygons new_internal_void = diff_ex(layerm->fill_surfaces.filter_by_type(stInternalVoid), shell);
|
||||
|
||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
{
|
||||
@ -1521,8 +1511,8 @@ void PrintObject::bridge_over_infill()
|
||||
#endif
|
||||
|
||||
// compute the remaning internal solid surfaces as difference
|
||||
ExPolygons not_to_bridge = diff_ex(internal_solid, to_polygons(to_bridge), true);
|
||||
to_bridge = intersection_ex(to_polygons(to_bridge), internal_solid, true);
|
||||
ExPolygons not_to_bridge = diff_ex(internal_solid, to_bridge, true);
|
||||
to_bridge = intersection_ex(to_bridge, internal_solid, true);
|
||||
// build the new collection of fill_surfaces
|
||||
layerm->fill_surfaces.remove_type(stInternalSolid);
|
||||
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);
|
||||
if (! processed.empty())
|
||||
// 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())
|
||||
// Collect the already processed regions to trim the to be processed regions.
|
||||
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];
|
||||
if (layerm == nullptr || other_layerm == nullptr || other_layerm->slices.empty() || expolygons_by_layer[layer_id].empty())
|
||||
continue;
|
||||
Polygons other_slices = to_polygons(other_layerm->slices);
|
||||
ExPolygons my_parts = intersection_ex(other_slices, to_polygons(expolygons_by_layer[layer_id]));
|
||||
ExPolygons my_parts = intersection_ex(other_layerm->slices.surfaces, expolygons_by_layer[layer_id]);
|
||||
if (my_parts.empty())
|
||||
continue;
|
||||
// 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.
|
||||
layerm->slices.append(std::move(my_parts), stInternal);
|
||||
}
|
||||
@ -2018,7 +2007,7 @@ end:
|
||||
slices = offset_ex(std::move(slices), xy_compensation_scaled);
|
||||
if (region_id > 0 && clip)
|
||||
// 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()))
|
||||
// Collect the already processed regions to trim the to be processed regions.
|
||||
polygons_append(processed, slices);
|
||||
@ -2649,10 +2638,7 @@ void PrintObject::discover_horizontal_shells()
|
||||
neighbor_layerm->fill_surfaces.set(internal_solid, stInternalSolid);
|
||||
// subtract intersections from layer surfaces to get resulting internal surfaces
|
||||
Polygons polygons_internal = to_polygons(std::move(internal_solid));
|
||||
ExPolygons internal = diff_ex(
|
||||
to_polygons(backup.filter_by_type(stInternal)),
|
||||
polygons_internal,
|
||||
true);
|
||||
ExPolygons internal = diff_ex(backup.filter_by_type(stInternal), polygons_internal, true);
|
||||
// assign resulting internal surfaces to layer
|
||||
neighbor_layerm->fill_surfaces.append(internal, stInternal);
|
||||
polygons_append(polygons_internal, to_polygons(std::move(internal)));
|
||||
@ -2663,7 +2649,7 @@ void PrintObject::discover_horizontal_shells()
|
||||
backup.group(&top_bottom_groups);
|
||||
for (SurfacesPtr &group : top_bottom_groups)
|
||||
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.
|
||||
*group.front());
|
||||
}
|
||||
@ -2742,10 +2728,7 @@ void PrintObject::combine_infill()
|
||||
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.
|
||||
for (size_t i = 1; i < layerms.size(); ++ i)
|
||||
intersection = intersection_ex(
|
||||
to_polygons(intersection),
|
||||
to_polygons(layerms[i]->fill_surfaces.filter_by_type(stInternal)),
|
||||
false);
|
||||
intersection = intersection_ex(layerms[i]->fill_surfaces.filter_by_type(stInternal), intersection);
|
||||
double area_threshold = layerms.front()->infill_area_threshold();
|
||||
if (! intersection.empty() && area_threshold > 0.)
|
||||
intersection.erase(std::remove_if(intersection.begin(), intersection.end(),
|
||||
@ -2774,7 +2757,7 @@ void PrintObject::combine_infill()
|
||||
for (ExPolygon &expoly : intersection)
|
||||
polygons_append(intersection_with_clearance, offset(expoly, clearance_offset));
|
||||
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.append(diff_ex(internal, intersection_with_clearance, false), stInternal);
|
||||
if (layerm == layerms.back()) {
|
||||
|
@ -179,9 +179,8 @@ static std::vector<SupportPointGenerator::MyLayer> make_layers(
|
||||
}
|
||||
}
|
||||
if (! top.islands_below.empty()) {
|
||||
Polygons top_polygons = to_polygons(*top.polygon);
|
||||
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()) {
|
||||
|
||||
// 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);
|
||||
|
||||
// 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
|
||||
// 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);
|
||||
dangl_mask = diff(dangl_mask, bottom_polygons);
|
||||
|
||||
top.dangling_areas = intersection_ex(top_polygons, dangl_mask);
|
||||
top.overhangs_slopes = intersection_ex(top_polygons, overh_mask);
|
||||
top.dangling_areas = intersection_ex(*top.polygon, dangl_mask);
|
||||
top.overhangs_slopes = intersection_ex(*top.polygon, overh_mask);
|
||||
|
||||
top.overhangs_area = 0.f;
|
||||
std::vector<std::pair<ExPolygon*, float>> expolys_with_areas;
|
||||
|
@ -90,7 +90,7 @@ public:
|
||||
float overlap_area(const Structure &rhs) const {
|
||||
double out = 0.;
|
||||
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)
|
||||
out += poly.area();
|
||||
}
|
||||
|
@ -815,7 +815,7 @@ public:
|
||||
// Expanding, thus m_support_polygons are all inside islands.
|
||||
union_ex(*m_support_polygons) :
|
||||
// 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;
|
||||
for (ExPolygon &island : islands) {
|
||||
@ -1437,7 +1437,7 @@ static inline std::tuple<Polygons, Polygons, Polygons, float> detect_overhangs(
|
||||
0.5f * fw);
|
||||
// Overhang polygons for this layer and region.
|
||||
Polygons diff_polygons;
|
||||
Polygons layerm_polygons = to_polygons(layerm->slices);
|
||||
Polygons layerm_polygons = to_polygons(layerm->slices.surfaces);
|
||||
if (lower_layer_offset == 0.f) {
|
||||
// Support everything.
|
||||
diff_polygons = diff(layerm_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
|
||||
// residues of diff_polygons that would then be supported.
|
||||
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
|
||||
@ -1538,7 +1538,7 @@ static inline std::tuple<Polygons, Polygons, Polygons, float> detect_overhangs(
|
||||
slices_margin.offset = slices_margin_offset;
|
||||
slices_margin.polygons = (slices_margin_offset == 0.f) ?
|
||||
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 (has_enforcer)
|
||||
// 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) {
|
||||
// Enforce supports (as if with 90 degrees of slope) for the regions covered by the enforcer meshes.
|
||||
#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
|
||||
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.
|
||||
offset(lower_layer_polygons, 0.05f * fw, SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
||||
#ifdef SLIC3R_DEBUG
|
||||
@ -2772,8 +2772,7 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object(
|
||||
break;
|
||||
some_region_overlaps = true;
|
||||
polygons_append(polygons_trimming,
|
||||
offset(to_expolygons(region->fill_surfaces.filter_by_type(stBottomBridge)),
|
||||
gap_xy_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
||||
offset(region->fill_surfaces.filter_by_type(stBottomBridge), gap_xy_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
||||
if (region->region()->config().overhangs.value)
|
||||
// Add bridging perimeters.
|
||||
SupportMaterialInternal::collect_bridging_perimeter_areas(region->perimeters, gap_xy_scaled, polygons_trimming);
|
||||
|
@ -90,7 +90,6 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator Polygons() const { return this->expolygon; }
|
||||
double area() const { return this->expolygon.area(); }
|
||||
bool empty() const { return expolygon.empty(); }
|
||||
void clear() { expolygon.clear(); }
|
||||
@ -107,6 +106,16 @@ public:
|
||||
typedef std::vector<Surface> Surfaces;
|
||||
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)
|
||||
{
|
||||
size_t num = 0;
|
||||
|
@ -6,18 +6,7 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
SurfaceCollection::operator Polygons() const
|
||||
{
|
||||
return to_polygons(surfaces);
|
||||
}
|
||||
|
||||
SurfaceCollection::operator ExPolygons() const
|
||||
{
|
||||
return to_expolygons(surfaces);
|
||||
}
|
||||
|
||||
void
|
||||
SurfaceCollection::simplify(double tolerance)
|
||||
void SurfaceCollection::simplify(double tolerance)
|
||||
{
|
||||
Surfaces ss;
|
||||
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 */
|
||||
void
|
||||
SurfaceCollection::group(std::vector<SurfacesPtr> *retval)
|
||||
void SurfaceCollection::group(std::vector<SurfacesPtr> *retval)
|
||||
{
|
||||
for (Surfaces::iterator it = this->surfaces.begin(); it != this->surfaces.end(); ++it) {
|
||||
// find a group with the same properties
|
||||
@ -54,8 +42,7 @@ SurfaceCollection::group(std::vector<SurfacesPtr> *retval)
|
||||
}
|
||||
}
|
||||
|
||||
SurfacesPtr
|
||||
SurfaceCollection::filter_by_type(const SurfaceType type)
|
||||
SurfacesPtr SurfaceCollection::filter_by_type(const SurfaceType type)
|
||||
{
|
||||
SurfacesPtr ss;
|
||||
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;
|
||||
}
|
||||
|
||||
SurfacesPtr
|
||||
SurfaceCollection::filter_by_types(const SurfaceType *types, int ntypes)
|
||||
SurfacesPtr SurfaceCollection::filter_by_types(const SurfaceType *types, int ntypes)
|
||||
{
|
||||
SurfacesPtr ss;
|
||||
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;
|
||||
}
|
||||
|
||||
void
|
||||
SurfaceCollection::filter_by_type(SurfaceType type, Polygons* polygons)
|
||||
void SurfaceCollection::filter_by_type(SurfaceType type, Polygons* polygons)
|
||||
{
|
||||
for (Surfaces::iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) {
|
||||
if (surface->surface_type == type) {
|
||||
@ -90,8 +75,7 @@ SurfaceCollection::filter_by_type(SurfaceType type, Polygons* polygons)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SurfaceCollection::keep_type(const SurfaceType type)
|
||||
void SurfaceCollection::keep_type(const SurfaceType type)
|
||||
{
|
||||
size_t j = 0;
|
||||
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());
|
||||
}
|
||||
|
||||
void
|
||||
SurfaceCollection::keep_types(const SurfaceType *types, int ntypes)
|
||||
void SurfaceCollection::keep_types(const SurfaceType *types, int ntypes)
|
||||
{
|
||||
size_t j = 0;
|
||||
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());
|
||||
}
|
||||
|
||||
void
|
||||
SurfaceCollection::remove_type(const SurfaceType type)
|
||||
void SurfaceCollection::remove_type(const SurfaceType type)
|
||||
{
|
||||
size_t j = 0;
|
||||
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());
|
||||
}
|
||||
|
||||
void
|
||||
SurfaceCollection::remove_types(const SurfaceType *types, int ntypes)
|
||||
void SurfaceCollection::remove_types(const SurfaceType *types, int ntypes)
|
||||
{
|
||||
size_t j = 0;
|
||||
for (size_t i = 0; i < surfaces.size(); ++ i) {
|
||||
|
@ -12,11 +12,10 @@ class SurfaceCollection
|
||||
public:
|
||||
Surfaces surfaces;
|
||||
|
||||
SurfaceCollection() {};
|
||||
SurfaceCollection() = default;
|
||||
SurfaceCollection(const Surfaces& surfaces) : surfaces(surfaces) {};
|
||||
SurfaceCollection(Surfaces &&surfaces) : surfaces(std::move(surfaces)) {};
|
||||
operator Polygons() const;
|
||||
operator ExPolygons() const;
|
||||
|
||||
void simplify(double tolerance);
|
||||
void group(std::vector<SurfacesPtr> *retval);
|
||||
template <class T> bool any_internal_contains(const T &item) const {
|
||||
|
@ -22,7 +22,7 @@ SCENARIO("Various Clipper operations - xs/t/11_clipper.t", "[ClipperUtils]") {
|
||||
THEN("offset matches") {
|
||||
REQUIRE(result == Polygons {
|
||||
{ { 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") {
|
||||
@ -56,7 +56,7 @@ SCENARIO("Various Clipper operations - xs/t/11_clipper.t", "[ClipperUtils]") {
|
||||
}
|
||||
GIVEN("square and hole") {
|
||||
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") {
|
||||
REQUIRE(result.size() == 1);
|
||||
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") {
|
||||
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") {
|
||||
REQUIRE(result.size() == 3);
|
||||
}
|
||||
@ -180,7 +180,7 @@ SCENARIO("Various Clipper operations - t/clipper.t", "[ClipperUtils]") {
|
||||
// CW oriented contour
|
||||
Slic3r::Polygon hole_in_square { { 14, 14 }, { 14, 16 }, { 16, 16 }, { 16, 14 } };
|
||||
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)") {
|
||||
ExPolygon match({ { 20, 18 }, { 10, 18 }, { 10, 12 }, { 20, 12 } },
|
||||
{ { 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") {
|
||||
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") {
|
||||
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()));
|
||||
@ -214,7 +214,7 @@ SCENARIO("Various Clipper operations - t/clipper.t", "[ClipperUtils]") {
|
||||
Slic3r::Polygon square { { 10, 10 }, { 20, 10 }, { 20, 20 }, { 10, 20 } };
|
||||
Slic3r::Polyline square_pl = square.split_at_first_point();
|
||||
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") {
|
||||
REQUIRE(res.size() == 1);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user