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; require Exporter;
our @ISA = qw(Exporter); our @ISA = qw(Exporter);
our @EXPORT_OK = qw(offset offset_ex our @EXPORT_OK = qw(offset offset_ex
diff_ex diff union_ex intersection_ex xor_ex JT_ROUND JT_MITER diff_ex diff union_ex intersection_ex JT_ROUND JT_MITER
JT_SQUARE is_counter_clockwise union_pt offset2 offset2_ex JT_SQUARE is_counter_clockwise offset2 offset2_ex
intersection intersection_pl diff_pl union intersection intersection_pl diff_pl union
union_pt_chained diff_ppl intersection_ppl); union_pt_chained);
1; 1;

View File

@ -7,7 +7,7 @@ use List::Util qw(min max sum first);
use Slic3r::Flow ':roles'; use Slic3r::Flow ':roles';
use Slic3r::Geometry qw(X Y Z PI scale unscale chained_path epsilon); 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 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::Print::State ':steps';
use Slic3r::Surface ':types'; use Slic3r::Surface ':types';

View File

@ -40,13 +40,13 @@ void BridgeDetector::initialize()
this->angle = -1.; this->angle = -1.;
// Outset our bridge by an arbitrary amout; we'll use this outer margin for detecting anchors. // 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 possible anchoring edges of this bridging region.
// Detect what edges lie on lower slices by turning bridge contour and holes // 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. // 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()). // 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 #ifdef SLIC3R_DEBUG
printf(" bridge has " PRINTF_ZU " support(s)\n", this->_edges.size()); printf(" bridge has " PRINTF_ZU " support(s)\n", this->_edges.size());
@ -117,7 +117,7 @@ BridgeDetector::detect_angle()
double total_length = 0; double total_length = 0;
double max_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) { for (size_t i = 0; i < clipped_lines.size(); ++i) {
const Line &line = clipped_lines[i]; const Line &line = clipped_lines[i];
if (expolygons_contain(this->_anchor_regions, line.a) && expolygons_contain(this->_anchor_regions, line.b)) { 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; return angles;
} }
void Polygons BridgeDetector::coverage(double angle) const
BridgeDetector::coverage(double angle, Polygons* coverage) const
{ {
if (angle == -1) angle = this->angle; if (angle == -1)
if (angle == -1) return; 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; 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);
/* Outset the bridge expolygon by half the amount we used for detecting anchors; if (angle != -1) {
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 // Get anchors, convert them to Polygons and rotate them.
Polygons trapezoids; Polygons anchors = to_polygons(this->_anchor_regions);
for (ExPolygons::const_iterator it = grown.begin(); it != grown.end(); ++it) polygons_rotate(anchors, PI/2.0 - angle);
it->get_trapezoids2(&trapezoids, PI/2.0);
for (Polygons::iterator trapezoid = trapezoids.begin(); trapezoid != trapezoids.end(); ++trapezoid) { for (ExPolygons::const_iterator it_expoly = this->expolygons.begin(); it_expoly != this->expolygons.end(); ++ it_expoly)
Lines supported = intersection(trapezoid->lines(), anchors); {
size_t n_supported = 0; // Clone our expolygon and rotate it so that we work with vertical lines.
// not nice, we need a more robust non-numeric check ExPolygon expolygon = *it_expoly;
for (size_t i = 0; i < supported.size(); ++i) expolygon.rotate(PI/2.0 - angle);
if (supported[i].length() >= this->spacing)
++ n_supported; /* Outset the bridge expolygon by half the amount we used for detecting anchors;
if (n_supported >= 2) we'll use this one to generate our trapezoids and be sure that their vertices
covered.push_back(STDMOVE(*trapezoid)); 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,
);
}
*/
} }
return covered;
// 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;
} }
/* This method returns the bridge edges (as polylines) that are not supported /* 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) { for (ExPolygons::const_iterator it_expoly = this->expolygons.begin(); it_expoly != this->expolygons.end(); ++ it_expoly) {
// get unsupported bridge edges (both contour and holes) // get unsupported bridge edges (both contour and holes)
Polylines unuspported_polylines; Lines unsupported_lines = to_lines(diff_pl(to_polylines(*it_expoly), grown_lower));
diff(to_polylines(*it_expoly), grown_lower, &unuspported_polylines);
Lines unsupported_lines = to_lines(unuspported_polylines);
/* Split into individual segments and filter out edges parallel to the bridging angle /* 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, 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 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(ExPolygon _expolygon, const ExPolygonCollection &_lower_slices, coord_t _extrusion_width);
BridgeDetector(const ExPolygons &_expolygons, const ExPolygonCollection &_lower_slices, coord_t _extrusion_width); BridgeDetector(const ExPolygons &_expolygons, const ExPolygonCollection &_lower_slices, coord_t _extrusion_width);
bool detect_angle(); bool detect_angle();
void coverage(double angle, Polygons* coverage) const;
Polygons coverage(double angle = -1) const; Polygons coverage(double angle = -1) const;
void unsupported_edges(double angle, Polylines* unsupported) const; void unsupported_edges(double angle, Polylines* unsupported) const;
Polylines unsupported_edges(double angle = -1) 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 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> template <class T>
void Slic3rMultiPoints_to_ClipperPaths(const T &input, ClipperLib::Paths* output); ClipperLib::Paths Slic3rMultiPoints_to_ClipperPaths(const T &input);
template <class T> template <class T>
void ClipperPath_to_Slic3rMultiPoint(const ClipperLib::Path &input, T* output); T ClipperPath_to_Slic3rMultiPoint(const ClipperLib::Path &input);
template <class T> template <class T>
void ClipperPaths_to_Slic3rMultiPoints(const ClipperLib::Paths &input, T* output); T ClipperPaths_to_Slic3rMultiPoints(const ClipperLib::Paths &input);
void ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input, Slic3r::ExPolygons* output); Slic3r::ExPolygons ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input);
void scaleClipperPolygons(ClipperLib::Paths &polygons, const double scale);
// offset Polygons // offset Polygons
void offset(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float delta, ClipperLib::Paths _offset(ClipperLib::Path &input, ClipperLib::EndType endType, const float delta, ClipperLib::JoinType joinType, double miterLimit);
ClipperLib::JoinType joinType = ClipperLib::jtMiter, ClipperLib::Paths _offset(ClipperLib::Paths &input, ClipperLib::EndType endType, const float delta, ClipperLib::JoinType joinType, double miterLimit);
double miterLimit = 3); inline Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
void offset(const Slic3r::Polygons &polygons, Slic3r::Polygons* retval, const float delta, { return ClipperPaths_to_Slic3rMultiPoints<Polygons>(_offset(Slic3rMultiPoint_to_ClipperPath(polygon), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); }
ClipperLib::JoinType joinType = ClipperLib::jtMiter, inline Slic3r::Polygons offset(const Slic3r::Polygons &polygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
double miterLimit = 3); { return ClipperPaths_to_Slic3rMultiPoints<Polygons>(_offset(Slic3rMultiPoints_to_ClipperPaths(polygons), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); }
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);
// offset Polylines // offset Polylines
void offset(const Slic3r::Polylines &polylines, ClipperLib::Paths* retval, const float delta, inline Slic3r::Polygons offset(const Slic3r::Polyline &polyline, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtSquare, double miterLimit = 3)
ClipperLib::JoinType joinType = ClipperLib::jtSquare, { return ClipperPaths_to_Slic3rMultiPoints<Polygons>(_offset(Slic3rMultiPoint_to_ClipperPath(polyline), ClipperLib::etOpenButt, delta, joinType, miterLimit)); }
double miterLimit = 3); inline Slic3r::Polygons offset(const Slic3r::Polylines &polylines, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtSquare, double miterLimit = 3)
void offset(const Slic3r::Polylines &polylines, Slic3r::Polygons* retval, const float delta, { return ClipperPaths_to_Slic3rMultiPoints<Polygons>(_offset(Slic3rMultiPoints_to_ClipperPaths(polylines), ClipperLib::etOpenButt, delta, joinType, miterLimit)); }
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);
void offset(const Slic3r::Polygons &polygons, Slic3r::ExPolygons* retval, const float delta, // offset expolygons and surfaces
ClipperLib::JoinType joinType = ClipperLib::jtMiter, ClipperLib::Paths _offset(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType, double miterLimit);
double miterLimit = 3); ClipperLib::Paths _offset(const Slic3r::ExPolygons &expolygons, const float delta, ClipperLib::JoinType joinType, double miterLimit);
Slic3r::ExPolygons offset_ex(const Slic3r::Polygons &polygons, const float delta, inline Slic3r::Polygons offset(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
ClipperLib::JoinType joinType = ClipperLib::jtMiter, { return ClipperPaths_to_Slic3rMultiPoints<Polygons>(_offset(expolygon, delta, joinType, miterLimit)); }
double miterLimit = 3); 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, ClipperLib::Paths _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::Polygons* retval, const float delta1,
const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter, const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
double miterLimit = 3); double miterLimit = 3);
Slic3r::Polygons offset2(const Slic3r::Polygons &polygons, const float delta1, Slic3r::Polygons offset2(const Slic3r::Polygons &polygons, const float delta1,
const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter, const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
double miterLimit = 3); 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, Slic3r::ExPolygons offset2_ex(const Slic3r::Polygons &polygons, const float delta1,
const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter, const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
double miterLimit = 3); double miterLimit = 3);
template <class T> template <class T>
void _clipper_do(ClipperLib::ClipType clipType, const Slic3r::Polygons &subject, T _clipper_do(ClipperLib::ClipType clipType, const Slic3r::Polygons &subject,
const Slic3r::Polygons &clip, T* retval, bool safety_offset_); const Slic3r::Polygons &clip, const ClipperLib::PolyFillType fillType, bool safety_offset_ = false);
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_);
template <class SubjectType, class ResultType> ClipperLib::PolyTree _clipper_do(ClipperLib::ClipType clipType, const Slic3r::Polylines &subject,
void diff(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_ = false); const Slic3r::Polygons &clip, const ClipperLib::PolyFillType fillType, bool safety_offset_ = false);
template <class SubjectType, class ResultType> Slic3r::Polygons _clipper(ClipperLib::ClipType clipType,
void diff(const SubjectType &subject, const Slic3r::ExPolygons &clip, ResultType* retval, bool safety_offset_ = false); 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); // diff
inline Slic3r::Polygons
template <class SubjectType, class ClipType> diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
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)
{ {
_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> inline Slic3r::ExPolygons
void intersection(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_ = false); diff_ex(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_ = false)
inline void intersection(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, Slic3r::Polylines* retval, 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> inline Slic3r::Polylines
SubjectType intersection(const SubjectType &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false); 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 inline Slic3r::Polylines
intersection_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false); 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> inline Slic3r::Lines
bool intersects(const SubjectType &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false); 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 inline Slic3r::Polylines
intersection_pl(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false) intersection_pl(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
{ {
Slic3r::Polylines polylines_out; return _clipper_pl(ClipperLib::ctIntersection, subject, clip, safety_offset_);
_clipper_pl(ClipperLib::ctIntersection, subject, clip, &polylines_out, safety_offset_);
return polylines_out;
} }
void xor_(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::ExPolygons* retval, inline Slic3r::Lines
bool safety_offset_ = false); 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> // union
void union_(const Slic3r::Polygons &subject, T* retval, bool safety_offset_ = false); 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); inline Slic3r::Polygons
Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject, bool safety_offset = false); union_(const Slic3r::Polygons &subject, const Slic3r::Polygons &subject2, bool safety_offset_ = false)
Slic3r::ExPolygons union_ex(const Slic3r::Surfaces &subject, 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); inline Slic3r::ExPolygons
Slic3r::Polygons union_(const Slic3r::ExPolygons &subject1, const Slic3r::ExPolygons &subject2, bool safety_offset = false); 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); inline Slic3r::ExPolygons
void union_pt_chained(const Slic3r::Polygons &subject, Slic3r::Polygons* retval, bool safety_offset_ = false); union_ex(const Slic3r::ExPolygons &subject, bool safety_offset_ = false)
static void traverse_pt(ClipperLib::PolyNodes &nodes, Slic3r::Polygons* retval); {
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); inline Slic3r::ExPolygons
void simplify_polygons(const Slic3r::Polygons &subject, Slic3r::ExPolygons* retval, bool preserve_collinear = false); 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); void safety_offset(ClipperLib::Paths* paths);

View File

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

View File

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

View File

@ -13,19 +13,13 @@ namespace Slic3r {
void void
ExtrusionPath::intersect_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const ExtrusionPath::intersect_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const
{ {
// perform clipping this->_inflate_collection(intersection_pl(this->polyline, collection), retval);
Polylines clipped;
intersection<Polylines,Polylines>(this->polyline, collection, &clipped);
return this->_inflate_collection(clipped, retval);
} }
void void
ExtrusionPath::subtract_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const ExtrusionPath::subtract_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const
{ {
// perform clipping this->_inflate_collection(diff_pl(this->polyline, collection), retval);
Polylines clipped;
diff<Polylines,Polylines>(this->polyline, collection, &clipped);
return this->_inflate_collection(clipped, retval);
} }
void 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 void ExtrusionPath::polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const
{ {
Polygons tmp; polygons_append(out, offset(this->polyline, float(scale_(this->width/2)) + scaled_epsilon));
offset(this->polyline, &tmp, scale_(this->width/2) + scaled_epsilon);
polygons_append(out, STDMOVE(tmp));
} }
void ExtrusionPath::polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const 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. // 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. // 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()); Flow flow(this->width, this->height, 0.f, this->is_bridge());
Polygons tmp; polygons_append(out, offset(this->polyline, 0.5f * float(flow.scaled_spacing()) + scaled_epsilon));
offset(this->polyline, &tmp, 0.5f * flow.scaled_spacing() + scaled_epsilon);
polygons_append(out, STDMOVE(tmp));
} }
bool bool

View File

@ -194,6 +194,26 @@ class ExtrusionLoop : public ExtrusionEntity
Polyline as_polyline() const { return this->polygon().split_at_first_point(); } 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) 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()); 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); it->translate(bb.min.x, bb.min.y);
// clip pattern to boundaries // clip pattern to boundaries
intersection(polylines, (Polygons)expolygon, &polylines); polylines = intersection_pl(polylines, (Polygons)expolygon);
// connect lines // connect lines
if (! params.dont_connect && ! polylines.empty()) { // prevent calling leftmost_point() on empty collections 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) Polylines Fill::fill_surface(const Surface *surface, const FillParams &params)
{ {
// Perform offset. // Perform offset.
Slic3r::ExPolygons expp; Slic3r::ExPolygons expp = offset_ex(surface->expolygon, float(-0.5*scale_(this->spacing)));
offset(surface->expolygon, &expp, -0.5*scale_(this->spacing));
// Create the infills for each of the regions. // Create the infills for each of the regions.
Polylines polylines_out; Polylines polylines_out;
for (size_t i = 0; i < expp.size(); ++ i) 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 // generate paths from the outermost to the innermost, to avoid
// adhesion problems of the first central tiny loops // adhesion problems of the first central tiny loops
union_pt_chained(loops, &loops, false); loops = union_pt_chained(loops, false);
// split paths using a nearest neighbor search // split paths using a nearest neighbor search
size_t iPathFirst = polylines_out.size(); size_t iPathFirst = polylines_out.size();

View File

@ -93,7 +93,7 @@ void FillHoneycomb::_fill_surface_single(
Polylines p; Polylines p;
for (Polygons::iterator it = polygons.begin(); it != polygons.end(); ++ it) for (Polygons::iterator it = polygons.begin(); it != polygons.end(); ++ it)
p.push_back((Polyline)(*it)); p.push_back((Polyline)(*it));
intersection(p, (Polygons)expolygon, &paths); paths = intersection_pl(p, to_polygons(expolygon));
} }
// connect paths // connect paths
@ -122,7 +122,7 @@ void FillHoneycomb::_fill_surface_single(
} }
// clip paths again to prevent connection segments from crossing the expolygon boundaries // 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. // Move the polylines to the output, avoid a deep copy.
size_t j = polylines_out.size(); size_t j = polylines_out.size();
polylines_out.resize(j + paths.size(), Polyline()); 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->x * distance_between_lines + 0.5)),
coord_t(floor(it->y * 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_src, offset((Polygons)expolygon, scale_(0.02)), &polylines);
intersection(polylines, (Polygons)expolygon, &polylines); polylines = intersection_pl(polylines, to_polygons(expolygon));
/* /*
if (1) { if (1) {

View File

@ -63,7 +63,7 @@ void FillRectilinear::_fill_surface_single(
pts.push_back(it->a); pts.push_back(it->a);
pts.push_back(it->b); 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! // FIXME Vojtech: This is only performed for horizontal lines, not for the vertical lines!
const float INFILL_OVERLAP_OVER_SPACING = 0.3f; 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 // avoid computing islands and overhangs if they're not needed
if (this->config.avoid_crossing_perimeters) { if (this->config.avoid_crossing_perimeters) {
ExPolygons islands; ExPolygons islands = union_ex(layer.slices, true);
union_(layer.slices, &islands, true);
this->avoid_crossing_perimeters.init_layer_mp(islands); this->avoid_crossing_perimeters.init_layer_mp(islands);
} }

View File

@ -105,7 +105,7 @@ Layer::make_slices()
FOREACH_LAYERREGION(this, layerm) { FOREACH_LAYERREGION(this, layerm) {
polygons_append(slices_p, to_polygons((*layerm)->slices)); polygons_append(slices_p, to_polygons((*layerm)->slices));
} }
union_(slices_p, &slices); slices = union_ex(slices_p);
} }
this->slices.expolygons.clear(); this->slices.expolygons.clear();
@ -132,15 +132,11 @@ Layer::merge_slices()
if (this->regions.size() == 1) { if (this->regions.size() == 1) {
// Optimization, also more robust. Don't merge classified pieces of layerm->slices, // 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. // but use the non-split islands of a layer. For a single region print, these shall be equal.
this->regions.front()->slices.surfaces.clear(); this->regions.front()->slices.set(this->slices.expolygons, stInternal);
surfaces_append(this->regions.front()->slices.surfaces, this->slices.expolygons, stInternal);
} else { } else {
FOREACH_LAYERREGION(this, layerm) { FOREACH_LAYERREGION(this, layerm) {
ExPolygons expp;
// without safety offset, artifacts are generated (GH #2494) // without safety offset, artifacts are generated (GH #2494)
union_(to_polygons(STDMOVE((*layerm)->slices.surfaces)), &expp, true); (*layerm)->slices.set(union_ex(to_polygons(STDMOVE((*layerm)->slices.surfaces)), true), stInternal);
(*layerm)->slices.surfaces.clear();
surfaces_append((*layerm)->slices.surfaces, expp, stInternal);
} }
} }
} }
@ -223,7 +219,7 @@ Layer::make_perimeters()
} }
// merge the surfaces assigned to each group // merge the surfaces assigned to each group
for (std::map<unsigned short,Surfaces>::const_iterator it = slices.begin(); it != slices.end(); ++it) 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 // make perimeters
@ -236,8 +232,7 @@ Layer::make_perimeters()
// Separate the fill surfaces. // Separate the fill surfaces.
ExPolygons expp = intersection_ex(to_polygons(fill_surfaces), (*l)->slices); ExPolygons expp = intersection_ex(to_polygons(fill_surfaces), (*l)->slices);
(*l)->fill_expolygons = expp; (*l)->fill_expolygons = expp;
(*l)->fill_surfaces.surfaces.clear(); (*l)->fill_surfaces.set(STDMOVE(expp), fill_surfaces.surfaces.front());
surfaces_append((*l)->fill_surfaces.surfaces, 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); Polygons fill_boundaries = to_polygons(this->fill_expolygons);
this->fill_surfaces.surfaces.clear(); this->fill_surfaces.surfaces.clear();
for (Surfaces::const_iterator surface = this->slices.surfaces.begin(); surface != this->slices.surfaces.end(); ++ surface) for (Surfaces::const_iterator surface = this->slices.surfaces.begin(); surface != this->slices.surfaces.end(); ++ surface)
surfaces_append( this->fill_surfaces.append(
this->fill_surfaces.surfaces,
intersection_ex(to_polygons(surface->expolygon), fill_boundaries), intersection_ex(to_polygons(surface->expolygon), fill_boundaries),
surface->surface_type); 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() // grow our environment slightly in order for simplify_by_visibility()
// to work best by considering moves on boundaries valid as well // 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 (island_idx == -1) {
/* If 'from' or 'to' are not inside our env, they were connected using the /* 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)) { if (!grown_env.contains(from)) {
// delete second point while the line connecting first to third crosses the // delete second point while the line connecting first to third crosses the
// boundaries as many times as the current first to second // 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); polyline.points.erase(polyline.points.begin() + 1);
} }
} }
if (!grown_env.contains(to)) { 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); 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); size_t result = from.nearest_waypoint_index(pp, to);
// as we assume 'from' is outside env, any node will require at least one crossing // 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 // discard result
pp.erase(pp.begin() + result); pp.erase(pp.begin() + result);
} else { } else {

View File

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

View File

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

View File

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

View File

@ -449,7 +449,7 @@ void PrintObject::detect_surfaces_type()
{ {
Polygons topbottom = to_polygons(top); Polygons topbottom = to_polygons(top);
polygons_append(topbottom, to_polygons(bottom)); polygons_append(topbottom, to_polygons(bottom));
surfaces_append(layerm->slices.surfaces, layerm->slices.append(
#if 0 #if 0
offset2_ex(diff(layerm_slices_surfaces, topbottom, true), -offset, offset), offset2_ex(diff(layerm_slices_surfaces, topbottom, true), -offset, offset),
#else #else
@ -458,8 +458,8 @@ void PrintObject::detect_surfaces_type()
stInternal); stInternal);
} }
surfaces_append(layerm->slices.surfaces, STDMOVE(top)); layerm->slices.append(STDMOVE(top));
surfaces_append(layerm->slices.surfaces, STDMOVE(bottom)); layerm->slices.append(STDMOVE(bottom));
// Slic3r::debugf " layer %d has %d bottom, %d top and %d internal surfaces\n", // 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; // $layerm->layer->id, scalar(@bottom), scalar(@top), scalar(@internal) if $Slic3r::debug;
@ -865,7 +865,7 @@ PrintObject::bridge_over_infill()
#endif #endif
// compute the remaning internal solid surfaces as difference // compute the remaning internal solid surfaces as difference
ExPolygons not_to_bridge = diff_ex(internal_solid, to_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); to_bridge = intersection_ex(to_polygons(to_bridge), internal_solid, true);
// build the new collection of fill_surfaces // build the new collection of fill_surfaces
@ -1011,7 +1011,7 @@ void PrintObject::_slice()
if (my_parts.empty()) if (my_parts.empty())
continue; continue;
// Remove such parts from original region. // Remove such parts from original region.
other_layerm->slices.set(diff_ex(other_slices, my_parts), stInternal); other_layerm->slices.set(diff_ex(other_slices, to_polygons(my_parts)), stInternal);
// Append new parts to our region. // Append new parts to our region.
layerm->slices.append(std::move(my_parts), stInternal); layerm->slices.append(std::move(my_parts), stInternal);
} }
@ -1039,7 +1039,7 @@ end:
if (layer->regions.size() == 1) { if (layer->regions.size() == 1) {
// single region // single region
LayerRegion *layerm = layer->regions.front(); 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 { } else {
if (delta < 0) { if (delta < 0) {
// multiple regions, shrinking // multiple regions, shrinking
@ -1060,7 +1060,7 @@ end:
Polygons processed; Polygons processed;
for (size_t region_id = 0;; ++ region_id) { for (size_t region_id = 0;; ++ region_id) {
LayerRegion *layerm = layer->regions[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) if (region_id > 0)
// Trim by the slices of already processed regions. // Trim by the slices of already processed regions.
slices = diff_ex(to_polygons(std::move(slices)), processed); slices = diff_ex(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() // workaround for Clipper bug, see Slic3r::Polygon::clip_as_polyline()
for (Polylines::iterator it = overhang_perimeters.begin(); it != overhang_perimeters.end(); ++ it) for (Polylines::iterator it = overhang_perimeters.begin(); it != overhang_perimeters.end(); ++ it)
it->points[0].x += 1; 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 straight overhangs
// only consider overhangs having endpoints inside layer's slices // only consider overhangs having endpoints inside layer's slices
@ -588,13 +588,9 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
if (it->is_straight()) { if (it->is_straight()) {
it->extend_start(fw); it->extend_start(fw);
it->extend_end(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. // Offset a polyline into a polygon.
Polylines tmp; tmp.push_back(*it); polygons_append(bridged_perimeters, offset(*it, 0.5f * w + 10.f));
Polygons out;
offset(tmp, &out, 0.5f * w + 10.f);
polygons_append(bridged_perimeters, out);
}
} }
} }
bridged_perimeters = union_(bridged_perimeters); bridged_perimeters = union_(bridged_perimeters);
@ -611,13 +607,9 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
Polygons unsupported_bridge_polygons; Polygons unsupported_bridge_polygons;
for (Polylines::const_iterator it = layerm.unsupported_bridge_edges.polylines.begin(); 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. // Offset a polyline into a polygon.
Polylines tmp; tmp.push_back(*it); polygons_append(unsupported_bridge_polygons, offset(*it, scale_(SUPPORT_MATERIAL_MARGIN)));
Polygons out;
offset(tmp, &out, scale_(SUPPORT_MATERIAL_MARGIN));
polygons_append(unsupported_bridge_polygons, out);
}
polygons_append(diff_polygons, intersection(unsupported_bridge_polygons, bridges)); polygons_append(diff_polygons, intersection(unsupported_bridge_polygons, bridges));
} else { } else {
// just remove bridged areas // just remove bridged areas
@ -1596,10 +1588,8 @@ void LoopInterfaceProcessor::generate(MyLayerExtruded &top_contact_layer, const
// Positions of the loop centers. // Positions of the loop centers.
Polygons circles; Polygons circles;
Polygons overhang_with_margin = offset(overhang_polygons, 0.5f * flow.scaled_width()); 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) { for (Polygons::const_iterator it_contact = top_contact_polygons.begin(); it_contact != top_contact_polygons.end(); ++ it_contact)
Polylines tmp; if (! intersection_pl(it_contact->split_at_first_point(), overhang_with_margin).empty()) {
tmp.push_back(it_contact->split_at_first_point());
if (! intersection(tmp, overhang_with_margin).empty()) {
external_loops.push_back(*it_contact); external_loops.push_back(*it_contact);
Points positions_new = it_contact->equally_spaced_points(circle_distance); 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) { 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); circle_new.points[i].translate(*it_center);
} }
} }
}
// Apply a pattern to the loop. // Apply a pattern to the loop.
loops0 = diff(external_loops, circles); loops0 = diff(external_loops, circles);
} }
@ -1628,7 +1617,7 @@ void LoopInterfaceProcessor::generate(MyLayerExtruded &top_contact_layer, const
loop_lines.reserve(loop_polygons.size()); loop_lines.reserve(loop_polygons.size());
for (Polygons::const_iterator it = loop_polygons.begin(); it != loop_polygons.end(); ++ it) for (Polygons::const_iterator it = loop_polygons.begin(); it != loop_polygons.end(); ++ it)
loop_lines.push_back(it->split_at_first_point()); 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 // 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 // extrusions are left inside the circles; however it creates
// a very large gap between loops and contact_infill_polygons, so maybe another // a very large gap between loops and contact_infill_polygons, so maybe another
// solution should be found to achieve both goals // solution should be found to achieve both goals
Polygons thick_loop_lines; top_contact_layer.layer->polygons = diff(top_contact_layer.layer->polygons, offset(loop_lines, float(circle_radius * 1.1)));
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));
// Transform loops into ExtrusionPath objects. // Transform loops into ExtrusionPath objects.
extrusion_entities_append_paths( extrusion_entities_append_paths(
@ -1857,7 +1844,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
// TODO: use brim ordering algorithm // TODO: use brim ordering algorithm
Polygons to_infill_polygons = to_polygons(to_infill); Polygons to_infill_polygons = to_polygons(to_infill);
// TODO: use offset2_ex() // 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( extrusion_entities_append_paths(
support_layer.support_fills.entities, support_layer.support_fills.entities,
to_polylines(STDMOVE(to_infill_polygons)), to_polylines(STDMOVE(to_infill_polygons)),

View File

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

View File

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

View File

@ -5,7 +5,7 @@ use warnings;
use List::Util qw(sum); use List::Util qw(sum);
use Slic3r::XS; use Slic3r::XS;
use Test::More tests => 23; use Test::More tests => 16;
my $square = Slic3r::Polygon->new( # ccw my $square = Slic3r::Polygon->new( # ccw
[200, 100], [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'; 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) # Clipper bug #96 (our issue #2028)
my $subject = Slic3r::Polyline->new( 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'; 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 # Clipper bug #122
my $subject = [ my $subject = [

View File

@ -27,7 +27,7 @@ offset(polygons, delta, joinType = ClipperLib::jtMiter, miterLimit = 3)
ClipperLib::JoinType joinType ClipperLib::JoinType joinType
double miterLimit double miterLimit
CODE: CODE:
offset(polygons, &RETVAL, delta, joinType, miterLimit); RETVAL = offset(polygons, delta, joinType, miterLimit);
OUTPUT: OUTPUT:
RETVAL RETVAL
@ -38,7 +38,7 @@ offset_ex(polygons, delta, joinType = ClipperLib::jtMiter, miterLimit = 3)
ClipperLib::JoinType joinType ClipperLib::JoinType joinType
double miterLimit double miterLimit
CODE: CODE:
offset(polygons, &RETVAL, delta, joinType, miterLimit); RETVAL = offset_ex(polygons, delta, joinType, miterLimit);
OUTPUT: OUTPUT:
RETVAL RETVAL
@ -50,7 +50,7 @@ offset2(polygons, delta1, delta2, joinType = ClipperLib::jtMiter, miterLimit = 3
ClipperLib::JoinType joinType ClipperLib::JoinType joinType
double miterLimit double miterLimit
CODE: CODE:
offset2(polygons, &RETVAL, delta1, delta2, joinType, miterLimit); RETVAL = offset2(polygons, delta1, delta2, joinType, miterLimit);
OUTPUT: OUTPUT:
RETVAL RETVAL
@ -62,7 +62,7 @@ offset2_ex(polygons, delta1, delta2, joinType = ClipperLib::jtMiter, miterLimit
ClipperLib::JoinType joinType ClipperLib::JoinType joinType
double miterLimit double miterLimit
CODE: CODE:
offset2(polygons, &RETVAL, delta1, delta2, joinType, miterLimit); RETVAL = offset2_ex(polygons, delta1, delta2, joinType, miterLimit);
OUTPUT: OUTPUT:
RETVAL RETVAL
@ -72,7 +72,7 @@ diff(subject, clip, safety_offset = false)
Polygons clip Polygons clip
bool safety_offset bool safety_offset
CODE: CODE:
diff(subject, clip, &RETVAL, safety_offset); RETVAL = diff(subject, clip, safety_offset);
OUTPUT: OUTPUT:
RETVAL RETVAL
@ -82,7 +82,7 @@ diff_ex(subject, clip, safety_offset = false)
Polygons clip Polygons clip
bool safety_offset bool safety_offset
CODE: CODE:
diff(subject, clip, &RETVAL, safety_offset); RETVAL = diff_ex(subject, clip, safety_offset);
OUTPUT: OUTPUT:
RETVAL RETVAL
@ -91,16 +91,7 @@ diff_pl(subject, clip)
Polylines subject Polylines subject
Polygons clip Polygons clip
CODE: CODE:
diff(subject, clip, &RETVAL); RETVAL = diff_pl(subject, clip);
OUTPUT:
RETVAL
Polylines
diff_ppl(subject, clip)
Polygons subject
Polygons clip
CODE:
diff(subject, clip, &RETVAL);
OUTPUT: OUTPUT:
RETVAL RETVAL
@ -110,7 +101,7 @@ intersection(subject, clip, safety_offset = false)
Polygons clip Polygons clip
bool safety_offset bool safety_offset
CODE: CODE:
intersection(subject, clip, &RETVAL, safety_offset); RETVAL = intersection(subject, clip, safety_offset);
OUTPUT: OUTPUT:
RETVAL RETVAL
@ -120,7 +111,7 @@ intersection_ex(subject, clip, safety_offset = false)
Polygons clip Polygons clip
bool safety_offset bool safety_offset
CODE: CODE:
intersection(subject, clip, &RETVAL, safety_offset); RETVAL = intersection_ex(subject, clip, safety_offset);
OUTPUT: OUTPUT:
RETVAL RETVAL
@ -129,26 +120,7 @@ intersection_pl(subject, clip)
Polylines subject Polylines subject
Polygons clip Polygons clip
CODE: CODE:
intersection(subject, clip, &RETVAL); RETVAL = intersection_pl(subject, clip);
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);
OUTPUT: OUTPUT:
RETVAL RETVAL
@ -157,7 +129,7 @@ union(subject, safety_offset = false)
Polygons subject Polygons subject
bool safety_offset bool safety_offset
CODE: CODE:
union_(subject, &RETVAL, safety_offset); RETVAL = union_(subject, safety_offset);
OUTPUT: OUTPUT:
RETVAL RETVAL
@ -166,20 +138,7 @@ union_ex(subject, safety_offset = false)
Polygons subject Polygons subject
bool safety_offset bool safety_offset
CODE: CODE:
union_(subject, &RETVAL, safety_offset); RETVAL = union_ex(subject, 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);
OUTPUT: OUTPUT:
RETVAL RETVAL
@ -188,7 +147,7 @@ union_pt_chained(subject, safety_offset = false)
Polygons subject Polygons subject
bool safety_offset bool safety_offset
CODE: CODE:
union_pt_chained(subject, &RETVAL, safety_offset); RETVAL = union_pt_chained(subject, safety_offset);
OUTPUT: OUTPUT:
RETVAL RETVAL
@ -196,7 +155,7 @@ Polygons
simplify_polygons(subject) simplify_polygons(subject)
Polygons subject Polygons subject
CODE: CODE:
simplify_polygons(subject, &RETVAL); RETVAL = simplify_polygons(subject);
OUTPUT: OUTPUT:
RETVAL RETVAL

View File

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

View File

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