Adapted to the new ClipperUtils.hpp interface by @alexrj

This commit is contained in:
bubnikv 2016-12-13 19:22:23 +01:00
parent b2a5a1d22f
commit 6582182e0c
31 changed files with 600 additions and 1122 deletions

View File

@ -5,9 +5,9 @@ use warnings;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(offset offset_ex
diff_ex diff union_ex intersection_ex xor_ex JT_ROUND JT_MITER
JT_SQUARE is_counter_clockwise union_pt offset2 offset2_ex
diff_ex diff union_ex intersection_ex JT_ROUND JT_MITER
JT_SQUARE is_counter_clockwise offset2 offset2_ex
intersection intersection_pl diff_pl union
union_pt_chained diff_ppl intersection_ppl);
union_pt_chained);
1;

View File

@ -7,7 +7,7 @@ use List::Util qw(min max sum first);
use Slic3r::Flow ':roles';
use Slic3r::Geometry qw(X Y Z PI scale unscale chained_path epsilon);
use Slic3r::Geometry::Clipper qw(diff diff_ex intersection intersection_ex union union_ex
offset offset_ex offset2 offset2_ex intersection_ppl JT_MITER);
offset offset_ex offset2 offset2_ex JT_MITER);
use Slic3r::Print::State ':steps';
use Slic3r::Surface ':types';

View File

@ -40,13 +40,13 @@ void BridgeDetector::initialize()
this->angle = -1.;
// Outset our bridge by an arbitrary amout; we'll use this outer margin for detecting anchors.
Polygons grown = offset(this->expolygons, float(this->spacing));
Polygons grown = offset(to_polygons(this->expolygons), float(this->spacing));
// Detect possible anchoring edges of this bridging region.
// Detect what edges lie on lower slices by turning bridge contour and holes
// into polylines and then clipping them with each lower slice's contour.
// Currently _edges are only used to set a candidate direction of the bridge (see bridge_direction_candidates()).
intersection(to_polylines(grown), this->lower_slices.contours(), &this->_edges);
this->_edges = intersection_pl(to_polylines(grown), this->lower_slices.contours());
#ifdef SLIC3R_DEBUG
printf(" bridge has " PRINTF_ZU " support(s)\n", this->_edges.size());
@ -117,7 +117,7 @@ BridgeDetector::detect_angle()
double total_length = 0;
double max_length = 0;
{
Lines clipped_lines = intersection(lines, clip_area);
Lines clipped_lines = intersection_ln(lines, clip_area);
for (size_t i = 0; i < clipped_lines.size(); ++i) {
const Line &line = clipped_lines[i];
if (expolygons_contain(this->_anchor_regions, line.a) && expolygons_contain(this->_anchor_regions, line.b)) {
@ -203,76 +203,72 @@ std::vector<double> BridgeDetector::bridge_direction_candidates() const
return angles;
}
void
BridgeDetector::coverage(double angle, Polygons* coverage) const
Polygons BridgeDetector::coverage(double angle) const
{
if (angle == -1) angle = this->angle;
if (angle == -1) return;
if (angle == -1)
angle = this->angle;
// Get anchors, convert them to Polygons and rotate them.
Polygons anchors = to_polygons(this->_anchor_regions);
polygons_rotate(anchors, PI/2.0 - angle);
Polygons covered;
for (ExPolygons::const_iterator it_expoly = this->expolygons.begin(); it_expoly != this->expolygons.end(); ++ it_expoly)
{
// Clone our expolygon and rotate it so that we work with vertical lines.
ExPolygon expolygon = *it_expoly;
expolygon.rotate(PI/2.0 - angle);
if (angle != -1) {
// Get anchors, convert them to Polygons and rotate them.
Polygons anchors = to_polygons(this->_anchor_regions);
polygons_rotate(anchors, PI/2.0 - angle);
/* Outset the bridge expolygon by half the amount we used for detecting anchors;
we'll use this one to generate our trapezoids and be sure that their vertices
are inside the anchors and not on their contours leading to false negatives. */
ExPolygons grown = offset_ex(expolygon, 0.5f * float(this->spacing));
// Compute trapezoids according to a vertical orientation
Polygons trapezoids;
for (ExPolygons::const_iterator it = grown.begin(); it != grown.end(); ++it)
it->get_trapezoids2(&trapezoids, PI/2.0);
for (Polygons::iterator trapezoid = trapezoids.begin(); trapezoid != trapezoids.end(); ++trapezoid) {
Lines supported = intersection(trapezoid->lines(), anchors);
size_t n_supported = 0;
// not nice, we need a more robust non-numeric check
for (size_t i = 0; i < supported.size(); ++i)
if (supported[i].length() >= this->spacing)
++ n_supported;
if (n_supported >= 2)
covered.push_back(STDMOVE(*trapezoid));
for (ExPolygons::const_iterator it_expoly = this->expolygons.begin(); it_expoly != this->expolygons.end(); ++ it_expoly)
{
// Clone our expolygon and rotate it so that we work with vertical lines.
ExPolygon expolygon = *it_expoly;
expolygon.rotate(PI/2.0 - angle);
/* Outset the bridge expolygon by half the amount we used for detecting anchors;
we'll use this one to generate our trapezoids and be sure that their vertices
are inside the anchors and not on their contours leading to false negatives. */
ExPolygons grown = offset_ex(expolygon, 0.5f * float(this->spacing));
// Compute trapezoids according to a vertical orientation
Polygons trapezoids;
for (ExPolygons::const_iterator it = grown.begin(); it != grown.end(); ++it)
it->get_trapezoids2(&trapezoids, PI/2.0);
for (Polygons::iterator trapezoid = trapezoids.begin(); trapezoid != trapezoids.end(); ++trapezoid) {
Lines supported = intersection_ln(trapezoid->lines(), anchors);
size_t n_supported = 0;
// not nice, we need a more robust non-numeric check
for (size_t i = 0; i < supported.size(); ++i)
if (supported[i].length() >= this->spacing)
++ n_supported;
if (n_supported >= 2)
covered.push_back(STDMOVE(*trapezoid));
}
}
// Unite the trapezoids before rotation, as the rotation creates tiny gaps and intersections between the trapezoids
// instead of exact overlaps.
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));
/*
if (0) {
my @lines = map @{$_->lines}, @$trapezoids;
$_->rotate(-(PI/2 - $angle), [0,0]) for @lines;
require "Slic3r/SVG.pm";
Slic3r::SVG::output(
"coverage_" . rad2deg($angle) . ".svg",
expolygons => [$self->expolygon],
green_expolygons => $self->_anchor_regions,
red_expolygons => $coverage,
lines => \@lines,
);
}
*/
}
// Unite the trapezoids before rotation, as the rotation creates tiny gaps and intersections between the trapezoids
// instead of exact overlaps.
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));
intersection(covered, to_polygons(this->expolygons), coverage);
/*
if (0) {
my @lines = map @{$_->lines}, @$trapezoids;
$_->rotate(-(PI/2 - $angle), [0,0]) for @lines;
require "Slic3r/SVG.pm";
Slic3r::SVG::output(
"coverage_" . rad2deg($angle) . ".svg",
expolygons => [$self->expolygon],
green_expolygons => $self->_anchor_regions,
red_expolygons => $coverage,
lines => \@lines,
);
}
*/
}
Polygons
BridgeDetector::coverage(double angle) const
{
Polygons pp;
this->coverage(angle, &pp);
return pp;
return covered;
}
/* This method returns the bridge edges (as polylines) that are not supported
@ -288,9 +284,7 @@ BridgeDetector::unsupported_edges(double angle, Polylines* unsupported) const
for (ExPolygons::const_iterator it_expoly = this->expolygons.begin(); it_expoly != this->expolygons.end(); ++ it_expoly) {
// get unsupported bridge edges (both contour and holes)
Polylines unuspported_polylines;
diff(to_polylines(*it_expoly), grown_lower, &unuspported_polylines);
Lines unsupported_lines = to_lines(unuspported_polylines);
Lines unsupported_lines = to_lines(diff_pl(to_polylines(*it_expoly), grown_lower));
/* Split into individual segments and filter out edges parallel to the bridging angle
TODO: angle tolerance should probably be based on segment length and flow width,
so that we build supports whenever there's a chance that at least one or two bridge

View File

@ -32,7 +32,6 @@ public:
BridgeDetector(ExPolygon _expolygon, const ExPolygonCollection &_lower_slices, coord_t _extrusion_width);
BridgeDetector(const ExPolygons &_expolygons, const ExPolygonCollection &_lower_slices, coord_t _extrusion_width);
bool detect_angle();
void coverage(double angle, Polygons* coverage) const;
Polygons coverage(double angle = -1) const;
void unsupported_edges(double angle, Polylines* unsupported) const;
Polylines unsupported_edges(double angle = -1) const;

File diff suppressed because it is too large Load Diff

View File

@ -20,166 +20,198 @@ void AddOuterPolyNodeToExPolygons(ClipperLib::PolyNode& polynode, Slic3r::ExPoly
void PolyTreeToExPolygons(ClipperLib::PolyTree& polytree, Slic3r::ExPolygons& expolygons);
//-----------------------------------------------------------
void Slic3rMultiPoint_to_ClipperPath(const Slic3r::MultiPoint &input, ClipperLib::Path* output);
ClipperLib::Path Slic3rMultiPoint_to_ClipperPath(const Slic3r::MultiPoint &input);
template <class T>
void Slic3rMultiPoints_to_ClipperPaths(const T &input, ClipperLib::Paths* output);
ClipperLib::Paths Slic3rMultiPoints_to_ClipperPaths(const T &input);
template <class T>
void ClipperPath_to_Slic3rMultiPoint(const ClipperLib::Path &input, T* output);
T ClipperPath_to_Slic3rMultiPoint(const ClipperLib::Path &input);
template <class T>
void ClipperPaths_to_Slic3rMultiPoints(const ClipperLib::Paths &input, T* output);
void ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input, Slic3r::ExPolygons* output);
void scaleClipperPolygons(ClipperLib::Paths &polygons, const double scale);
T ClipperPaths_to_Slic3rMultiPoints(const ClipperLib::Paths &input);
Slic3r::ExPolygons ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input);
// offset Polygons
void offset(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float delta,
ClipperLib::JoinType joinType = ClipperLib::jtMiter,
double miterLimit = 3);
void offset(const Slic3r::Polygons &polygons, Slic3r::Polygons* retval, 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);
// 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.
void offset(const Slic3r::ExPolygon &expolygon, ClipperLib::Paths* retval, const float delta,
ClipperLib::JoinType joinType = ClipperLib::jtMiter,
double miterLimit = 3);
void offset(const Slic3r::ExPolygons &expolygons, ClipperLib::Paths* retval, const float delta,
ClipperLib::JoinType joinType = ClipperLib::jtMiter,
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::ExPolygons offset_ex(const Slic3r::ExPolygon &expolygon, const float delta,
double scale, ClipperLib::JoinType joinType, double miterLimit);
Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygons &expolygons, const float delta,
double scale, ClipperLib::JoinType joinType, double miterLimit);
ClipperLib::Paths _offset(ClipperLib::Path &input, ClipperLib::EndType endType, const float delta, ClipperLib::JoinType joinType, double miterLimit);
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_Slic3rMultiPoints<Polygons>(_offset(Slic3rMultiPoint_to_ClipperPath(polygon), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); }
inline Slic3r::Polygons offset(const Slic3r::Polygons &polygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
{ return ClipperPaths_to_Slic3rMultiPoints<Polygons>(_offset(Slic3rMultiPoints_to_ClipperPaths(polygons), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); }
// offset Polylines
void offset(const Slic3r::Polylines &polylines, ClipperLib::Paths* retval, const float delta,
ClipperLib::JoinType joinType = ClipperLib::jtSquare,
double miterLimit = 3);
void offset(const Slic3r::Polylines &polylines, Slic3r::Polygons* retval, const float delta,
ClipperLib::JoinType joinType = ClipperLib::jtSquare,
double miterLimit = 3);
void offset(const Slic3r::Surface &surface, Slic3r::Surfaces* retval, const float delta,
ClipperLib::JoinType joinType = ClipperLib::jtSquare,
double miterLimit = 3);
inline Slic3r::Polygons offset(const Slic3r::Polyline &polyline, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtSquare, double miterLimit = 3)
{ return ClipperPaths_to_Slic3rMultiPoints<Polygons>(_offset(Slic3rMultiPoint_to_ClipperPath(polyline), ClipperLib::etOpenButt, delta, joinType, miterLimit)); }
inline Slic3r::Polygons offset(const Slic3r::Polylines &polylines, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtSquare, double miterLimit = 3)
{ return ClipperPaths_to_Slic3rMultiPoints<Polygons>(_offset(Slic3rMultiPoints_to_ClipperPaths(polylines), ClipperLib::etOpenButt, delta, joinType, miterLimit)); }
void offset(const Slic3r::Polygons &polygons, Slic3r::ExPolygons* retval, 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);
// 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 ClipperPaths_to_Slic3rMultiPoints<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 ClipperPaths_to_Slic3rMultiPoints<Polygons>(_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)); }
inline Slic3r::ExPolygons offset_ex(const Slic3r::Polygons &polygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
{ return ClipperPaths_to_Slic3rExPolygons(_offset(Slic3rMultiPoints_to_ClipperPaths(polygons), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); }
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)); }
void offset2(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float delta1,
const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
double miterLimit = 3);
void offset2(const Slic3r::Polygons &polygons, Slic3r::Polygons* retval, const float delta1,
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);
void offset2(const Slic3r::Polygons &polygons, Slic3r::ExPolygons* retval, 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);
template <class T>
void _clipper_do(ClipperLib::ClipType clipType, const Slic3r::Polygons &subject,
const Slic3r::Polygons &clip, T* retval, bool safety_offset_);
void _clipper_do(ClipperLib::ClipType clipType, const Slic3r::Polylines &subject,
const Slic3r::Polygons &clip, ClipperLib::Paths* retval, bool safety_offset_);
void _clipper(ClipperLib::ClipType clipType, const Slic3r::Polygons &subject,
const Slic3r::Polygons &clip, Slic3r::Polygons* retval, bool safety_offset_);
void _clipper(ClipperLib::ClipType clipType, const Slic3r::Polygons &subject,
const Slic3r::Polygons &clip, Slic3r::ExPolygons* retval, bool safety_offset_);
void _clipper_pl(ClipperLib::ClipType clipType, const Slic3r::Polylines &subject,
const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_);
void _clipper_ln(ClipperLib::ClipType clipType, const Slic3r::Lines &subject,
const Slic3r::Polygons &clip, Slic3r::Lines* retval, bool safety_offset_);
T _clipper_do(ClipperLib::ClipType clipType, const Slic3r::Polygons &subject,
const Slic3r::Polygons &clip, const ClipperLib::PolyFillType fillType, bool safety_offset_ = false);
template <class SubjectType, class ResultType>
void diff(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_ = false);
ClipperLib::PolyTree _clipper_do(ClipperLib::ClipType clipType, const Slic3r::Polylines &subject,
const Slic3r::Polygons &clip, const ClipperLib::PolyFillType fillType, bool safety_offset_ = false);
template <class SubjectType, class ResultType>
void diff(const SubjectType &subject, const Slic3r::ExPolygons &clip, ResultType* retval, bool safety_offset_ = false);
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);
Slic3r::Polygons diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false);
template <class SubjectType, class ClipType>
Slic3r::ExPolygons diff_ex(const SubjectType &subject, const ClipType &clip, bool safety_offset_ = false);
inline void diff(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_ = false)
// diff
inline Slic3r::Polygons
diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
{
_clipper_pl(ClipperLib::ctDifference, subject, clip, retval, safety_offset_);
return _clipper(ClipperLib::ctDifference, subject, clip, safety_offset_);
}
inline void diff(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, Slic3r::Lines* retval, bool safety_offset_ = false)
inline Slic3r::ExPolygons
diff_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
{
_clipper_ln(ClipperLib::ctDifference, subject, clip, retval, safety_offset_);
return _clipper_ex(ClipperLib::ctDifference, subject, clip, safety_offset_);
}
template <class SubjectType, class ResultType>
void intersection(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_ = false);
inline void intersection(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_ = false)
inline Slic3r::ExPolygons
diff_ex(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_ = false)
{
_clipper_pl(ClipperLib::ctIntersection, subject, clip, retval, safety_offset_);
return _clipper_ex(ClipperLib::ctDifference, to_polygons(subject), to_polygons(clip), safety_offset_);
}
inline void intersection(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, Slic3r::Lines* retval, bool safety_offset_ = false)
inline Slic3r::Polygons
diff(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_ = false)
{
_clipper_ln(ClipperLib::ctIntersection, subject, clip, retval, safety_offset_);
return _clipper(ClipperLib::ctDifference, to_polygons(subject), to_polygons(clip), safety_offset_);
}
template <class SubjectType>
SubjectType intersection(const SubjectType &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false);
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_);
}
Slic3r::ExPolygons
intersection_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false);
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_);
}
template <class SubjectType>
bool intersects(const SubjectType &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false);
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)
{
Slic3r::Polylines polylines_out;
_clipper_pl(ClipperLib::ctIntersection, subject, clip, &polylines_out, safety_offset_);
return polylines_out;
return _clipper_pl(ClipperLib::ctIntersection, subject, clip, safety_offset_);
}
void xor_(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::ExPolygons* retval,
bool safety_offset_ = false);
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_);
}
template <class T>
void union_(const Slic3r::Polygons &subject, T* retval, bool safety_offset_ = false);
// union
inline Slic3r::Polygons
union_(const Slic3r::Polygons &subject, bool safety_offset_ = false)
{
return _clipper(ClipperLib::ctUnion, subject, Slic3r::Polygons(), safety_offset_);
}
Slic3r::Polygons union_(const Slic3r::Polygons &subject, bool safety_offset = false);
Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject, bool safety_offset = false);
Slic3r::ExPolygons union_ex(const Slic3r::Surfaces &subject, bool safety_offset = false);
inline Slic3r::Polygons
union_(const Slic3r::Polygons &subject, const Slic3r::Polygons &subject2, bool safety_offset_ = false)
{
return _clipper(ClipperLib::ctUnion, subject, subject2, safety_offset_);
}
void union_(const Slic3r::Polygons &subject1, const Slic3r::Polygons &subject2, Slic3r::Polygons* retval, bool safety_offset = false);
Slic3r::Polygons union_(const Slic3r::ExPolygons &subject1, const Slic3r::ExPolygons &subject2, bool safety_offset = false);
inline Slic3r::ExPolygons
union_ex(const Slic3r::Polygons &subject, bool safety_offset_ = false)
{
return _clipper_ex(ClipperLib::ctUnion, subject, Slic3r::Polygons(), safety_offset_);
}
void union_pt(const Slic3r::Polygons &subject, ClipperLib::PolyTree* retval, bool safety_offset_ = false);
void union_pt_chained(const Slic3r::Polygons &subject, Slic3r::Polygons* retval, bool safety_offset_ = false);
static void traverse_pt(ClipperLib::PolyNodes &nodes, Slic3r::Polygons* retval);
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_);
}
void simplify_polygons(const Slic3r::Polygons &subject, Slic3r::Polygons* retval, bool preserve_collinear = false);
void simplify_polygons(const Slic3r::Polygons &subject, Slic3r::ExPolygons* retval, bool preserve_collinear = false);
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);
Slic3r::Polygons union_pt_chained(const Slic3r::Polygons &subject, bool safety_offset_ = false);
void traverse_pt(ClipperLib::PolyNodes &nodes, Slic3r::Polygons* retval);
/* OTHER */
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);
void safety_offset(ClipperLib::Paths* paths);
@ -187,4 +219,4 @@ Polygons top_level_islands(const Slic3r::Polygons &polygons);
}
#endif
#endif

View File

@ -12,8 +12,9 @@
namespace Slic3r {
namespace EdgeGrid {
struct Grid
class Grid
{
public:
Grid();
~Grid();

View File

@ -99,9 +99,7 @@ ExPolygon::contains(const Line &line) const
bool
ExPolygon::contains(const Polyline &polyline) const
{
Polylines pl_out;
diff((Polylines)polyline, *this, &pl_out);
return pl_out.empty();
return diff_pl((Polylines)polyline, *this).empty();
}
bool
@ -115,8 +113,7 @@ ExPolygon::contains(const Polylines &polylines) const
svg.draw_outline(*this);
svg.draw(polylines, "blue");
#endif
Polylines pl_out;
diff(polylines, *this, &pl_out);
Polylines pl_out = diff_pl(polylines, *this);
#if 0
svg.draw(pl_out, "red");
#endif
@ -162,8 +159,7 @@ ExPolygon::overlaps(const ExPolygon &other) const
svg.draw_outline(*this);
svg.draw_outline(other, "blue");
#endif
Polylines pl_out;
intersection((Polylines)other, *this, &pl_out);
Polylines pl_out = intersection_pl((Polylines)other, *this);
#if 0
svg.draw(pl_out, "red");
#endif
@ -396,11 +392,8 @@ ExPolygon::get_trapezoids2(Polygons* polygons) const
poly[3].y = bb.max.y;
// intersect with this expolygon
Polygons trapezoids;
intersection<Polygons,Polygons>(poly, *this, &trapezoids);
// append results to return value
polygons->insert(polygons->end(), trapezoids.begin(), trapezoids.end());
polygons_append(*polygons, intersection(poly, to_polygons(*this)));
}
}
@ -434,16 +427,13 @@ ExPolygon::triangulate_pp(Polygons* polygons) const
// convert polygons
std::list<TPPLPoly> input;
Polygons pp = *this;
simplify_polygons(pp, &pp, true);
ExPolygons expp;
union_(pp, &expp);
ExPolygons expp = union_ex(simplify_polygons(to_polygons(*this), true));
for (ExPolygons::const_iterator ex = expp.begin(); ex != expp.end(); ++ex) {
// contour
{
TPPLPoly p;
p.Init(ex->contour.points.size());
p.Init(int(ex->contour.points.size()));
//printf(PRINTF_ZU "\n0\n", ex->contour.points.size());
for (Points::const_iterator point = ex->contour.points.begin(); point != ex->contour.points.end(); ++point) {
p[ point-ex->contour.points.begin() ].x = point->x;
@ -480,8 +470,8 @@ ExPolygon::triangulate_pp(Polygons* polygons) const
Polygon p;
p.points.resize(num_points);
for (long i = 0; i < num_points; ++i) {
p.points[i].x = (*poly)[i].x;
p.points[i].y = (*poly)[i].y;
p.points[i].x = coord_t((*poly)[i].x);
p.points[i].y = coord_t((*poly)[i].y);
}
polygons->push_back(p);
}
@ -490,8 +480,7 @@ ExPolygon::triangulate_pp(Polygons* polygons) const
void
ExPolygon::triangulate_p2t(Polygons* polygons) const
{
ExPolygons expp;
simplify_polygons(*this, &expp, true);
ExPolygons expp = simplify_polygons_ex(*this, true);
for (ExPolygons::const_iterator ex = expp.begin(); ex != expp.end(); ++ex) {
// TODO: prevent duplicate points

View File

@ -13,19 +13,13 @@ namespace Slic3r {
void
ExtrusionPath::intersect_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const
{
// perform clipping
Polylines clipped;
intersection<Polylines,Polylines>(this->polyline, collection, &clipped);
return this->_inflate_collection(clipped, retval);
this->_inflate_collection(intersection_pl(this->polyline, collection), retval);
}
void
ExtrusionPath::subtract_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const
{
// perform clipping
Polylines clipped;
diff<Polylines,Polylines>(this->polyline, collection, &clipped);
return this->_inflate_collection(clipped, retval);
this->_inflate_collection(diff_pl(this->polyline, collection), retval);
}
void
@ -58,9 +52,7 @@ ExtrusionPath::_inflate_collection(const Polylines &polylines, ExtrusionEntityCo
void ExtrusionPath::polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const
{
Polygons tmp;
offset(this->polyline, &tmp, scale_(this->width/2) + scaled_epsilon);
polygons_append(out, STDMOVE(tmp));
polygons_append(out, offset(this->polyline, float(scale_(this->width/2)) + scaled_epsilon));
}
void ExtrusionPath::polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const
@ -68,9 +60,7 @@ void ExtrusionPath::polygons_covered_by_spacing(Polygons &out, const float scale
// Instantiating the Flow class to get the line spacing.
// Don't know the nozzle diameter, setting to zero. It shall not matter it shall be optimized out by the compiler.
Flow flow(this->width, this->height, 0.f, this->is_bridge());
Polygons tmp;
offset(this->polyline, &tmp, 0.5f * flow.scaled_spacing() + scaled_epsilon);
polygons_append(out, STDMOVE(tmp));
polygons_append(out, offset(this->polyline, 0.5f * float(flow.scaled_spacing()) + scaled_epsilon));
}
bool

View File

@ -194,6 +194,26 @@ class ExtrusionLoop : public ExtrusionEntity
Polyline as_polyline() const { return this->polygon().split_at_first_point(); }
};
inline void extrusion_paths_append(ExtrusionPaths &dst, Polylines &polylines, ExtrusionRole role, double mm3_per_mm, float width, float height)
{
dst.reserve(dst.size() + polylines.size());
for (Polylines::const_iterator it_polyline = polylines.begin(); it_polyline != polylines.end(); ++ it_polyline) {
dst.push_back(ExtrusionPath(role, mm3_per_mm, width, height));
dst.back().polyline = *it_polyline;
}
}
#if SLIC3R_CPPVER >= 11
inline void extrusion_paths_append(ExtrusionPaths &dst, Polylines &&polylines, ExtrusionRole role, double mm3_per_mm, float width, float height)
{
dst.reserve(dst.size() + polylines.size());
for (Polylines::const_iterator it_polyline = polylines.begin(); it_polyline != polylines.end(); ++ it_polyline) {
dst.push_back(ExtrusionPath(role, mm3_per_mm, width, height));
dst.back().polyline = std::move(*it_polyline);
}
}
#endif // SLIC3R_CPPVER >= 11
inline void extrusion_entities_append_paths(ExtrusionEntitiesPtr &dst, Polylines &polylines, ExtrusionRole role, double mm3_per_mm, float width, float height)
{
dst.reserve(dst.size() + polylines.size());

View File

@ -168,7 +168,7 @@ void Fill3DHoneycomb::_fill_surface_single(
it->translate(bb.min.x, bb.min.y);
// clip pattern to boundaries
intersection(polylines, (Polygons)expolygon, &polylines);
polylines = intersection_pl(polylines, (Polygons)expolygon);
// connect lines
if (! params.dont_connect && ! polylines.empty()) { // prevent calling leftmost_point() on empty collections

View File

@ -45,8 +45,7 @@ Fill* Fill::new_from_type(const std::string &type)
Polylines Fill::fill_surface(const Surface *surface, const FillParams &params)
{
// Perform offset.
Slic3r::ExPolygons expp;
offset(surface->expolygon, &expp, -0.5*scale_(this->spacing));
Slic3r::ExPolygons expp = offset_ex(surface->expolygon, float(-0.5*scale_(this->spacing)));
// Create the infills for each of the regions.
Polylines polylines_out;
for (size_t i = 0; i < expp.size(); ++ i)

View File

@ -33,7 +33,7 @@ void FillConcentric::_fill_surface_single(
// generate paths from the outermost to the innermost, to avoid
// adhesion problems of the first central tiny loops
union_pt_chained(loops, &loops, false);
loops = union_pt_chained(loops, false);
// split paths using a nearest neighbor search
size_t iPathFirst = polylines_out.size();

View File

@ -93,7 +93,7 @@ void FillHoneycomb::_fill_surface_single(
Polylines p;
for (Polygons::iterator it = polygons.begin(); it != polygons.end(); ++ it)
p.push_back((Polyline)(*it));
intersection(p, (Polygons)expolygon, &paths);
paths = intersection_pl(p, to_polygons(expolygon));
}
// connect paths
@ -122,7 +122,7 @@ void FillHoneycomb::_fill_surface_single(
}
// clip paths again to prevent connection segments from crossing the expolygon boundaries
intersection(paths, to_polygons(offset_ex(expolygon, SCALED_EPSILON)), &paths);
paths = intersection_pl(paths, to_polygons(offset_ex(expolygon, SCALED_EPSILON)));
// Move the polylines to the output, avoid a deep copy.
size_t j = polylines_out.size();
polylines_out.resize(j + paths.size(), Polyline());

View File

@ -44,7 +44,7 @@ void FillPlanePath::_fill_surface_single(
coord_t(floor(it->x * distance_between_lines + 0.5)),
coord_t(floor(it->y * distance_between_lines + 0.5))));
// intersection(polylines_src, offset((Polygons)expolygon, scale_(0.02)), &polylines);
intersection(polylines, (Polygons)expolygon, &polylines);
polylines = intersection_pl(polylines, to_polygons(expolygon));
/*
if (1) {

View File

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

View File

@ -315,8 +315,7 @@ GCode::change_layer(const Layer &layer)
// avoid computing islands and overhangs if they're not needed
if (this->config.avoid_crossing_perimeters) {
ExPolygons islands;
union_(layer.slices, &islands, true);
ExPolygons islands = union_ex(layer.slices, true);
this->avoid_crossing_perimeters.init_layer_mp(islands);
}

View File

@ -105,7 +105,7 @@ Layer::make_slices()
FOREACH_LAYERREGION(this, layerm) {
polygons_append(slices_p, to_polygons((*layerm)->slices));
}
union_(slices_p, &slices);
slices = union_ex(slices_p);
}
this->slices.expolygons.clear();
@ -132,15 +132,11 @@ Layer::merge_slices()
if (this->regions.size() == 1) {
// Optimization, also more robust. Don't merge classified pieces of layerm->slices,
// but use the non-split islands of a layer. For a single region print, these shall be equal.
this->regions.front()->slices.surfaces.clear();
surfaces_append(this->regions.front()->slices.surfaces, this->slices.expolygons, stInternal);
this->regions.front()->slices.set(this->slices.expolygons, stInternal);
} else {
FOREACH_LAYERREGION(this, layerm) {
ExPolygons expp;
// without safety offset, artifacts are generated (GH #2494)
union_(to_polygons(STDMOVE((*layerm)->slices.surfaces)), &expp, true);
(*layerm)->slices.surfaces.clear();
surfaces_append((*layerm)->slices.surfaces, expp, stInternal);
(*layerm)->slices.set(union_ex(to_polygons(STDMOVE((*layerm)->slices.surfaces)), true), stInternal);
}
}
}
@ -223,7 +219,7 @@ Layer::make_perimeters()
}
// merge the surfaces assigned to each group
for (std::map<unsigned short,Surfaces>::const_iterator it = slices.begin(); it != slices.end(); ++it)
surfaces_append(new_slices.surfaces, union_ex(it->second, true), it->second.front());
new_slices.append(union_ex(it->second, true), it->second.front());
}
// make perimeters
@ -236,8 +232,7 @@ Layer::make_perimeters()
// Separate the fill surfaces.
ExPolygons expp = intersection_ex(to_polygons(fill_surfaces), (*l)->slices);
(*l)->fill_expolygons = expp;
(*l)->fill_surfaces.surfaces.clear();
surfaces_append((*l)->fill_surfaces.surfaces, STDMOVE(expp), fill_surfaces.surfaces.front());
(*l)->fill_surfaces.set(STDMOVE(expp), fill_surfaces.surfaces.front());
}
}
}

View File

@ -52,8 +52,7 @@ void LayerRegion::slices_to_fill_surfaces_clipped()
Polygons fill_boundaries = to_polygons(this->fill_expolygons);
this->fill_surfaces.surfaces.clear();
for (Surfaces::const_iterator surface = this->slices.surfaces.begin(); surface != this->slices.surfaces.end(); ++ surface)
surfaces_append(
this->fill_surfaces.surfaces,
this->fill_surfaces.append(
intersection_ex(to_polygons(surface->expolygon), fill_boundaries),
surface->surface_type);
}

View File

@ -142,7 +142,7 @@ MotionPlanner::shortest_path(const Point &from, const Point &to)
{
// grow our environment slightly in order for simplify_by_visibility()
// to work best by considering moves on boundaries valid as well
ExPolygonCollection grown_env(offset_ex(env.env, +SCALED_EPSILON));
ExPolygonCollection grown_env(offset_ex(env.env.expolygons, +SCALED_EPSILON));
if (island_idx == -1) {
/* If 'from' or 'to' are not inside our env, they were connected using the
@ -155,12 +155,12 @@ MotionPlanner::shortest_path(const Point &from, const Point &to)
if (!grown_env.contains(from)) {
// delete second point while the line connecting first to third crosses the
// boundaries as many times as the current first to second
while (polyline.points.size() > 2 && intersection((Lines)Line(from, polyline.points[2]), grown_env).size() == 1) {
while (polyline.points.size() > 2 && intersection_ln((Lines)Line(from, polyline.points[2]), grown_env).size() == 1) {
polyline.points.erase(polyline.points.begin() + 1);
}
}
if (!grown_env.contains(to)) {
while (polyline.points.size() > 2 && intersection((Lines)Line(*(polyline.points.end() - 3), to), grown_env).size() == 1) {
while (polyline.points.size() > 2 && intersection_ln((Lines)Line(*(polyline.points.end() - 3), to), grown_env).size() == 1) {
polyline.points.erase(polyline.points.end() - 2);
}
}
@ -294,7 +294,7 @@ MotionPlannerEnv::nearest_env_point(const Point &from, const Point &to) const
size_t result = from.nearest_waypoint_index(pp, to);
// as we assume 'from' is outside env, any node will require at least one crossing
if (intersection((Lines)Line(from, pp[result]), this->island).size() > 1) {
if (intersection_ln((Lines)Line(from, pp[result]), this->island).size() > 1) {
// discard result
pp.erase(pp.begin() + result);
} else {

View File

@ -314,8 +314,7 @@ PerimeterGenerator::process()
coord_t min_perimeter_infill_spacing = ispacing * (1 - INSET_OVERLAP_TOLERANCE);
// append infill areas to fill_surfaces
surfaces_append(
this->fill_surfaces->surfaces,
this->fill_surfaces->append(
offset2_ex(
pp,
-inset -min_perimeter_infill_spacing/2,
@ -353,36 +352,24 @@ PerimeterGenerator::_traverse_loops(const PerimeterGeneratorLoops &loops,
if (this->config->overhangs && this->layer_id > 0
&& !(this->object_config->support_material && this->object_config->support_material_contact_distance.value == 0)) {
// get non-overhang paths by intersecting this loop with the grown lower slices
{
Polylines polylines;
intersection((Polygons)loop->polygon, this->_lower_slices_p, &polylines);
for (Polylines::const_iterator polyline = polylines.begin(); polyline != polylines.end(); ++polyline) {
ExtrusionPath path(role);
path.polyline = *polyline;
path.mm3_per_mm = is_external ? this->_ext_mm3_per_mm : this->_mm3_per_mm;
path.width = is_external ? this->ext_perimeter_flow.width : this->perimeter_flow.width;
path.height = this->layer_height;
paths.push_back(path);
}
}
extrusion_paths_append(
paths,
intersection_pl(loop->polygon, this->_lower_slices_p),
role,
is_external ? this->_ext_mm3_per_mm : this->_mm3_per_mm,
is_external ? this->ext_perimeter_flow.width : this->perimeter_flow.width,
this->layer_height);
// get overhang paths by checking what parts of this loop fall
// outside the grown lower slices (thus where the distance between
// the loop centerline and original lower slices is >= half nozzle diameter
{
Polylines polylines;
diff((Polygons)loop->polygon, this->_lower_slices_p, &polylines);
for (Polylines::const_iterator polyline = polylines.begin(); polyline != polylines.end(); ++polyline) {
ExtrusionPath path(erOverhangPerimeter);
path.polyline = *polyline;
path.mm3_per_mm = this->_mm3_per_mm_overhang;
path.width = this->overhang_flow.width;
path.height = this->overhang_flow.height;
paths.push_back(path);
}
}
extrusion_paths_append(
paths,
diff_pl(loop->polygon, this->_lower_slices_p),
erOverhangPerimeter,
this->_mm3_per_mm_overhang,
this->overhang_flow.width,
this->overhang_flow.height);
// reapply the nearest point search for starting point
// We allow polyline reversal because Clipper may have randomly

View File

@ -112,9 +112,7 @@ double Polygon::area() const
bool
Polygon::is_counter_clockwise() const
{
ClipperLib::Path p;
Slic3rMultiPoint_to_ClipperPath(*this, &p);
return ClipperLib::Orientation(p);
return ClipperLib::Orientation(Slic3rMultiPoint_to_ClipperPath(*this));
}
bool
@ -190,8 +188,7 @@ Polygon::simplify(double tolerance) const
Polygons pp;
pp.push_back(p);
simplify_polygons(pp, &pp);
return pp;
return simplify_polygons(pp);
}
void

View File

@ -608,20 +608,15 @@ Print::validate() const
object->model_object()->instances.front()->transform_polygon(&convex_hull);
// grow convex hull with the clearance margin
{
Polygons grown_hull;
offset(convex_hull, &grown_hull, scale_(this->config.extruder_clearance_radius.value)/2, jtRound, scale_(0.1));
convex_hull = grown_hull.front();
}
convex_hull = offset(convex_hull, scale_(this->config.extruder_clearance_radius.value)/2, jtRound, scale_(0.1)).front();
// now we check that no instance of convex_hull intersects any of the previously checked object instances
for (Points::const_iterator copy = object->_shifted_copies.begin(); copy != object->_shifted_copies.end(); ++copy) {
Polygon p = convex_hull;
p.translate(*copy);
if (intersects(a, p))
if (! intersection(a, p).empty())
return "Some objects are too close; your extruder will collide with them.";
union_(a, p, &a);
polygons_append(a, p);
}
}
}

View File

@ -449,7 +449,7 @@ void PrintObject::detect_surfaces_type()
{
Polygons topbottom = to_polygons(top);
polygons_append(topbottom, to_polygons(bottom));
surfaces_append(layerm->slices.surfaces,
layerm->slices.append(
#if 0
offset2_ex(diff(layerm_slices_surfaces, topbottom, true), -offset, offset),
#else
@ -458,8 +458,8 @@ void PrintObject::detect_surfaces_type()
stInternal);
}
surfaces_append(layerm->slices.surfaces, STDMOVE(top));
surfaces_append(layerm->slices.surfaces, STDMOVE(bottom));
layerm->slices.append(STDMOVE(top));
layerm->slices.append(STDMOVE(bottom));
// Slic3r::debugf " layer %d has %d bottom, %d top and %d internal surfaces\n",
// $layerm->layer->id, scalar(@bottom), scalar(@top), scalar(@internal) if $Slic3r::debug;
@ -865,7 +865,7 @@ PrintObject::bridge_over_infill()
#endif
// compute the remaning internal solid surfaces as difference
ExPolygons not_to_bridge = diff_ex(internal_solid, to_bridge, true);
ExPolygons not_to_bridge = diff_ex(internal_solid, to_polygons(to_bridge), true);
to_bridge = intersection_ex(to_polygons(to_bridge), internal_solid, true);
// build the new collection of fill_surfaces
@ -1011,7 +1011,7 @@ void PrintObject::_slice()
if (my_parts.empty())
continue;
// Remove such parts from original region.
other_layerm->slices.set(diff_ex(other_slices, my_parts), stInternal);
other_layerm->slices.set(diff_ex(other_slices, to_polygons(my_parts)), stInternal);
// Append new parts to our region.
layerm->slices.append(std::move(my_parts), stInternal);
}
@ -1039,7 +1039,7 @@ end:
if (layer->regions.size() == 1) {
// single region
LayerRegion *layerm = layer->regions.front();
layerm->slices.set(offset_ex(to_polygons(std::move(layerm->slices.surfaces)), delta), stInternal);
layerm->slices.set(offset_ex(to_expolygons(std::move(layerm->slices.surfaces)), delta), stInternal);
} else {
if (delta < 0) {
// multiple regions, shrinking
@ -1060,7 +1060,7 @@ end:
Polygons processed;
for (size_t region_id = 0;; ++ region_id) {
LayerRegion *layerm = layer->regions[region_id];
ExPolygons slices = offset_ex(to_polygons(layerm->slices.surfaces), delta);
ExPolygons slices = offset_ex(to_expolygons(layerm->slices.surfaces), delta);
if (region_id > 0)
// Trim by the slices of already processed regions.
slices = diff_ex(to_polygons(std::move(slices)), processed);

View File

@ -575,7 +575,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
// workaround for Clipper bug, see Slic3r::Polygon::clip_as_polyline()
for (Polylines::iterator it = overhang_perimeters.begin(); it != overhang_perimeters.end(); ++ it)
it->points[0].x += 1;
diff(overhang_perimeters, lower_grown_slices, &overhang_perimeters);
overhang_perimeters = diff_pl(overhang_perimeters, lower_grown_slices);
// only consider straight overhangs
// only consider overhangs having endpoints inside layer's slices
@ -588,13 +588,9 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
if (it->is_straight()) {
it->extend_start(fw);
it->extend_end(fw);
if (layer.slices.contains(it->first_point()) && layer.slices.contains(it->last_point())) {
if (layer.slices.contains(it->first_point()) && layer.slices.contains(it->last_point()))
// Offset a polyline into a polygon.
Polylines tmp; tmp.push_back(*it);
Polygons out;
offset(tmp, &out, 0.5f * w + 10.f);
polygons_append(bridged_perimeters, out);
}
polygons_append(bridged_perimeters, offset(*it, 0.5f * w + 10.f));
}
}
bridged_perimeters = union_(bridged_perimeters);
@ -611,13 +607,9 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
Polygons unsupported_bridge_polygons;
for (Polylines::const_iterator it = layerm.unsupported_bridge_edges.polylines.begin();
it != layerm.unsupported_bridge_edges.polylines.end(); ++ it) {
it != layerm.unsupported_bridge_edges.polylines.end(); ++ it)
// Offset a polyline into a polygon.
Polylines tmp; tmp.push_back(*it);
Polygons out;
offset(tmp, &out, scale_(SUPPORT_MATERIAL_MARGIN));
polygons_append(unsupported_bridge_polygons, out);
}
polygons_append(unsupported_bridge_polygons, offset(*it, scale_(SUPPORT_MATERIAL_MARGIN)));
polygons_append(diff_polygons, intersection(unsupported_bridge_polygons, bridges));
} else {
// just remove bridged areas
@ -1596,10 +1588,8 @@ void LoopInterfaceProcessor::generate(MyLayerExtruded &top_contact_layer, const
// Positions of the loop centers.
Polygons circles;
Polygons overhang_with_margin = offset(overhang_polygons, 0.5f * flow.scaled_width());
for (Polygons::const_iterator it_contact = top_contact_polygons.begin(); it_contact != top_contact_polygons.end(); ++ it_contact) {
Polylines tmp;
tmp.push_back(it_contact->split_at_first_point());
if (! intersection(tmp, overhang_with_margin).empty()) {
for (Polygons::const_iterator it_contact = top_contact_polygons.begin(); it_contact != top_contact_polygons.end(); ++ it_contact)
if (! intersection_pl(it_contact->split_at_first_point(), overhang_with_margin).empty()) {
external_loops.push_back(*it_contact);
Points positions_new = it_contact->equally_spaced_points(circle_distance);
for (Points::const_iterator it_center = positions_new.begin(); it_center != positions_new.end(); ++ it_center) {
@ -1609,7 +1599,6 @@ void LoopInterfaceProcessor::generate(MyLayerExtruded &top_contact_layer, const
circle_new.points[i].translate(*it_center);
}
}
}
// Apply a pattern to the loop.
loops0 = diff(external_loops, circles);
}
@ -1628,7 +1617,7 @@ void LoopInterfaceProcessor::generate(MyLayerExtruded &top_contact_layer, const
loop_lines.reserve(loop_polygons.size());
for (Polygons::const_iterator it = loop_polygons.begin(); it != loop_polygons.end(); ++ it)
loop_lines.push_back(it->split_at_first_point());
loop_lines = intersection(loop_lines, offset(overhang_polygons, scale_(SUPPORT_MATERIAL_MARGIN)));
loop_lines = intersection_pl(loop_lines, offset(overhang_polygons, scale_(SUPPORT_MATERIAL_MARGIN)));
}
// add the contact infill area to the interface area
@ -1636,9 +1625,7 @@ void LoopInterfaceProcessor::generate(MyLayerExtruded &top_contact_layer, const
// extrusions are left inside the circles; however it creates
// a very large gap between loops and contact_infill_polygons, so maybe another
// solution should be found to achieve both goals
Polygons thick_loop_lines;
offset(loop_lines, &thick_loop_lines, float(circle_radius * 1.1));
top_contact_layer.layer->polygons = diff(top_contact_layer.layer->polygons, std::move(thick_loop_lines));
top_contact_layer.layer->polygons = diff(top_contact_layer.layer->polygons, offset(loop_lines, float(circle_radius * 1.1)));
// Transform loops into ExtrusionPath objects.
extrusion_entities_append_paths(
@ -1857,7 +1844,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
// TODO: use brim ordering algorithm
Polygons to_infill_polygons = to_polygons(to_infill);
// TODO: use offset2_ex()
to_infill = offset_ex(to_infill_polygons, - flow.scaled_spacing());
to_infill = offset_ex(to_infill, - flow.scaled_spacing());
extrusion_entities_append_paths(
support_layer.support_fills.entities,
to_polylines(STDMOVE(to_infill_polygons)),

View File

@ -370,10 +370,7 @@ TriangleMesh::horizontal_projection() const
}
// the offset factor was tuned using groovemount.stl
offset(pp, &pp, 0.01 / SCALING_FACTOR);
ExPolygons retval;
union_(pp, &retval, true);
return retval;
return union_ex(offset(pp, 0.01 / SCALING_FACTOR), true);
}
Polygon
@ -852,17 +849,15 @@ TriangleMeshSlicer::make_expolygons(const Polygons &loops, ExPolygons* slices) c
of the loops, since the Orientation() function provided by Clipper
would do the same, thus repeating the calculation */
Polygons::const_iterator loop = loops.begin() + *loop_idx;
if (area[*loop_idx] > +EPSILON) {
if (area[*loop_idx] > +EPSILON)
p_slices.push_back(*loop);
} else if (area[*loop_idx] < -EPSILON) {
diff(p_slices, *loop, &p_slices);
}
else if (area[*loop_idx] < -EPSILON)
p_slices = diff(p_slices, *loop);
}
// perform a safety offset to merge very close facets (TODO: find test case for this)
double safety_offset = scale_(0.0499);
ExPolygons ex_slices;
offset2(p_slices, &ex_slices, +safety_offset, -safety_offset);
ExPolygons ex_slices = offset2_ex(p_slices, +safety_offset, -safety_offset);
#ifdef SLIC3R_TRIANGLEMESH_DEBUG
size_t holes_count = 0;
@ -874,7 +869,7 @@ TriangleMeshSlicer::make_expolygons(const Polygons &loops, ExPolygons* slices) c
#endif
// append to the supplied collection
slices->insert(slices->end(), ex_slices.begin(), ex_slices.end());
expolygons_append(*slices, ex_slices);
}
void

View File

@ -532,8 +532,7 @@ SV*
polynode2perl(const ClipperLib::PolyNode& node)
{
HV* hv = newHV();
Slic3r::Polygon p;
ClipperPath_to_Slic3rMultiPoint(node.Contour, &p);
Slic3r::Polygon p = ClipperPath_to_Slic3rMultiPoint<Slic3r::Polygon>(node.Contour);
if (node.IsHole()) {
(void)hv_stores( hv, "hole", Slic3r::perl_to_SV_clone_ref(p) );
} else {

View File

@ -5,7 +5,7 @@ use warnings;
use List::Util qw(sum);
use Slic3r::XS;
use Test::More tests => 23;
use Test::More tests => 16;
my $square = Slic3r::Polygon->new( # ccw
[200, 100],
@ -121,41 +121,6 @@ if (0) { # Clipper does not preserve polyline orientation
is_deeply $result->[0]->pp, [[200,150], [100,150]], 'clipped line orientation is preserved';
}
if (0) { # Clipper does not preserve polyline orientation
my $result = Slic3r::Geometry::Clipper::intersection_ppl([$hole_in_square], [$square]);
is_deeply $result->[0]->pp, $hole_in_square->split_at_first_point->pp,
'intersection_ppl - clipping cw polygon as polyline preserves winding order';
}
{
my $square2 = $square->clone;
$square2->translate(50,50);
{
my $result = Slic3r::Geometry::Clipper::intersection_ppl([$square2], [$square]);
is scalar(@$result), 1, 'intersection_ppl - result contains a single line';
is scalar(@{$result->[0]}), 3, 'intersection_ppl - result contains expected number of points';
# Clipper does not preserve polyline orientation so we only check the middle point
###ok $result->[0][0]->coincides_with(Slic3r::Point->new(150,200)), 'intersection_ppl - expected point order';
ok $result->[0][1]->coincides_with(Slic3r::Point->new(150,150)), 'intersection_ppl - expected point order';
###ok $result->[0][2]->coincides_with(Slic3r::Point->new(200,150)), 'intersection_ppl - expected point order';
}
}
{
my $square2 = $square->clone;
$square2->reverse;
$square2->translate(50,50);
{
my $result = Slic3r::Geometry::Clipper::intersection_ppl([$square2], [$square]);
is scalar(@$result), 1, 'intersection_ppl - result contains a single line';
is scalar(@{$result->[0]}), 3, 'intersection_ppl - result contains expected number of points';
# Clipper does not preserve polyline orientation so we only check the middle point
###ok $result->[0][0]->coincides_with(Slic3r::Point->new(200,150)), 'intersection_ppl - expected point order';
ok $result->[0][1]->coincides_with(Slic3r::Point->new(150,150)), 'intersection_ppl - expected point order';
###ok $result->[0][2]->coincides_with(Slic3r::Point->new(150,200)), 'intersection_ppl - expected point order';
}
}
{
# Clipper bug #96 (our issue #2028)
my $subject = Slic3r::Polyline->new(
@ -168,17 +133,6 @@ if (0) { # Clipper does not preserve polyline orientation
is scalar(@$result), 1, 'intersection_pl - result is not empty';
}
{
my $subject = Slic3r::Polygon->new(
[44730000,31936670],[55270000,31936670],[55270000,25270000],[74730000,25270000],[74730000,44730000],[68063296,44730000],[68063296,55270000],[74730000,55270000],[74730000,74730000],[55270000,74730000],[55270000,68063296],[44730000,68063296],[44730000,74730000],[25270000,74730000],[25270000,55270000],[31936670,55270000],[31936670,44730000],[25270000,44730000],[25270000,25270000],[44730000,25270000]
);
my $clip = [
Slic3r::Polygon->new([75200000,45200000],[54800000,45200000],[54800000,24800000],[75200000,24800000]),
];
my $result = Slic3r::Geometry::Clipper::intersection_ppl([$subject], $clip);
is scalar(@$result), 1, 'intersection_ppl - result is not empty';
}
{
# Clipper bug #122
my $subject = [

View File

@ -27,7 +27,7 @@ offset(polygons, delta, joinType = ClipperLib::jtMiter, miterLimit = 3)
ClipperLib::JoinType joinType
double miterLimit
CODE:
offset(polygons, &RETVAL, delta, joinType, miterLimit);
RETVAL = offset(polygons, delta, joinType, miterLimit);
OUTPUT:
RETVAL
@ -38,7 +38,7 @@ offset_ex(polygons, delta, joinType = ClipperLib::jtMiter, miterLimit = 3)
ClipperLib::JoinType joinType
double miterLimit
CODE:
offset(polygons, &RETVAL, delta, joinType, miterLimit);
RETVAL = offset_ex(polygons, delta, joinType, miterLimit);
OUTPUT:
RETVAL
@ -50,7 +50,7 @@ offset2(polygons, delta1, delta2, joinType = ClipperLib::jtMiter, miterLimit = 3
ClipperLib::JoinType joinType
double miterLimit
CODE:
offset2(polygons, &RETVAL, delta1, delta2, joinType, miterLimit);
RETVAL = offset2(polygons, delta1, delta2, joinType, miterLimit);
OUTPUT:
RETVAL
@ -62,7 +62,7 @@ offset2_ex(polygons, delta1, delta2, joinType = ClipperLib::jtMiter, miterLimit
ClipperLib::JoinType joinType
double miterLimit
CODE:
offset2(polygons, &RETVAL, delta1, delta2, joinType, miterLimit);
RETVAL = offset2_ex(polygons, delta1, delta2, joinType, miterLimit);
OUTPUT:
RETVAL
@ -72,7 +72,7 @@ diff(subject, clip, safety_offset = false)
Polygons clip
bool safety_offset
CODE:
diff(subject, clip, &RETVAL, safety_offset);
RETVAL = diff(subject, clip, safety_offset);
OUTPUT:
RETVAL
@ -82,7 +82,7 @@ diff_ex(subject, clip, safety_offset = false)
Polygons clip
bool safety_offset
CODE:
diff(subject, clip, &RETVAL, safety_offset);
RETVAL = diff_ex(subject, clip, safety_offset);
OUTPUT:
RETVAL
@ -91,16 +91,7 @@ diff_pl(subject, clip)
Polylines subject
Polygons clip
CODE:
diff(subject, clip, &RETVAL);
OUTPUT:
RETVAL
Polylines
diff_ppl(subject, clip)
Polygons subject
Polygons clip
CODE:
diff(subject, clip, &RETVAL);
RETVAL = diff_pl(subject, clip);
OUTPUT:
RETVAL
@ -110,7 +101,7 @@ intersection(subject, clip, safety_offset = false)
Polygons clip
bool safety_offset
CODE:
intersection(subject, clip, &RETVAL, safety_offset);
RETVAL = intersection(subject, clip, safety_offset);
OUTPUT:
RETVAL
@ -120,7 +111,7 @@ intersection_ex(subject, clip, safety_offset = false)
Polygons clip
bool safety_offset
CODE:
intersection(subject, clip, &RETVAL, safety_offset);
RETVAL = intersection_ex(subject, clip, safety_offset);
OUTPUT:
RETVAL
@ -129,26 +120,7 @@ intersection_pl(subject, clip)
Polylines subject
Polygons clip
CODE:
intersection(subject, clip, &RETVAL);
OUTPUT:
RETVAL
Polylines
intersection_ppl(subject, clip)
Polygons subject
Polygons clip
CODE:
intersection(subject, clip, &RETVAL);
OUTPUT:
RETVAL
ExPolygons
xor_ex(subject, clip, safety_offset = false)
Polygons subject
Polygons clip
bool safety_offset
CODE:
xor_(subject, clip, &RETVAL, safety_offset);
RETVAL = intersection_pl(subject, clip);
OUTPUT:
RETVAL
@ -157,7 +129,7 @@ union(subject, safety_offset = false)
Polygons subject
bool safety_offset
CODE:
union_(subject, &RETVAL, safety_offset);
RETVAL = union_(subject, safety_offset);
OUTPUT:
RETVAL
@ -166,20 +138,7 @@ union_ex(subject, safety_offset = false)
Polygons subject
bool safety_offset
CODE:
union_(subject, &RETVAL, safety_offset);
OUTPUT:
RETVAL
SV*
union_pt(subject, safety_offset = false)
Polygons subject
bool safety_offset
CODE:
// perform operation
ClipperLib::PolyTree polytree;
union_pt(subject, &polytree, safety_offset);
RETVAL = polynode_children_2_perl(polytree);
RETVAL = union_ex(subject, safety_offset);
OUTPUT:
RETVAL
@ -188,7 +147,7 @@ union_pt_chained(subject, safety_offset = false)
Polygons subject
bool safety_offset
CODE:
union_pt_chained(subject, &RETVAL, safety_offset);
RETVAL = union_pt_chained(subject, safety_offset);
OUTPUT:
RETVAL
@ -196,7 +155,7 @@ Polygons
simplify_polygons(subject)
Polygons subject
CODE:
simplify_polygons(subject, &RETVAL);
RETVAL = simplify_polygons(subject);
OUTPUT:
RETVAL

View File

@ -85,7 +85,7 @@ Polyline::grow(delta, joinType = ClipperLib::jtSquare, miterLimit = 3)
ClipperLib::JoinType joinType
double miterLimit
CODE:
offset(*THIS, &RETVAL, delta, joinType, miterLimit);
RETVAL = offset(*THIS, delta, joinType, miterLimit);
OUTPUT:
RETVAL

View File

@ -88,7 +88,7 @@ Surface::offset(delta, joinType = ClipperLib::jtMiter, miterLimit = 3)
ClipperLib::JoinType joinType
double miterLimit
CODE:
offset(*THIS, &RETVAL, delta, joinType, miterLimit);
surfaces_append(RETVAL, offset_ex(THIS->expolygon, delta, joinType, miterLimit), *THIS);
OUTPUT:
RETVAL