Skip to content

Commit

Permalink
Fix of prusa3d#117: A large fractal pyramid takes ages to slice
Browse files Browse the repository at this point in the history
The Clipper library has difficulties processing overlapping polygons.
Namely, the function Clipper::JoinCommonEdges() has potentially a terrible time complexity if the output
of the operation is of the PolyTree type.
This function implmenets a following workaround:
1) Peform the Clipper operation with the output to Paths. This method handles overlaps in a reasonable time.
2) Run Clipper Union once again to extract the PolyTree from the result of 1).

Conflicts:

	xs/src/libslic3r/ClipperUtils.cpp
  • Loading branch information
bubnikv authored and alranel committed Mar 8, 2017
1 parent 412498b commit c4929c3
Showing 1 changed file with 38 additions and 1 deletion.
39 changes: 38 additions & 1 deletion xs/src/libslic3r/ClipperUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,43 @@ _clipper_do(const ClipperLib::ClipType clipType, const Polygons &subject,
return retval;
}

// The Clipper library has difficulties processing overlapping polygons.
// Namely, the function Clipper::JoinCommonEdges() has potentially a terrible time complexity if the output
// of the operation is of the PolyTree type.
// This function implements a following workaround:
// 1) Peform the Clipper operation with the output to Paths. This method handles overlaps in a reasonable time.
// 2) Run Clipper Union once again to extract the PolyTree from the result of 1).
inline ClipperLib::PolyTree _clipper_do_polytree2(const ClipperLib::ClipType clipType, const Polygons &subject,
const Polygons &clip, const ClipperLib::PolyFillType fillType, const bool safety_offset_)
{
// read input
ClipperLib::Paths input_subject = Slic3rMultiPoints_to_ClipperPaths(subject);
ClipperLib::Paths input_clip = Slic3rMultiPoints_to_ClipperPaths(clip);

// perform safety offset
if (safety_offset_) {
if (clipType == ClipperLib::ctUnion) {
safety_offset(&input_subject);
} else {
safety_offset(&input_clip);
}
}

ClipperLib::Clipper clipper;
clipper.AddPaths(input_subject, ClipperLib::ptSubject, true);
clipper.AddPaths(input_clip, ClipperLib::ptClip, true);
// Perform the operation with the output to input_subject.
// This pass does not generate a PolyTree, which is a very expensive operation with the current Clipper library
// if there are overlapping edges.
clipper.Execute(clipType, input_subject, fillType, fillType);
// Perform an additional Union operation to generate the PolyTree ordering.
clipper.Clear();
clipper.AddPaths(input_subject, ClipperLib::ptSubject, true);
ClipperLib::PolyTree retval;
clipper.Execute(ClipperLib::ctUnion, retval, fillType, fillType);
return retval;
}

ClipperLib::PolyTree
_clipper_do(const ClipperLib::ClipType clipType, const Polylines &subject,
const Polygons &clip, const ClipperLib::PolyFillType fillType,
Expand Down Expand Up @@ -337,7 +374,7 @@ _clipper_ex(ClipperLib::ClipType clipType, const Polygons &subject,
const Polygons &clip, bool safety_offset_)
{
// perform operation
ClipperLib::PolyTree polytree = _clipper_do<ClipperLib::PolyTree>(clipType, subject, clip, ClipperLib::pftNonZero, safety_offset_);
ClipperLib::PolyTree polytree = _clipper_do_polytree2(clipType, subject, clip, ClipperLib::pftNonZero, safety_offset_);

// convert into ExPolygons
return PolyTreeToExPolygons(polytree);
Expand Down

0 comments on commit c4929c3

Please sign in to comment.