Adapted to the new ClipperUtils.hpp interface by @alexrj
This commit is contained in:
parent
b2a5a1d22f
commit
6582182e0c
@ -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;
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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;
|
||||
|
||||
// Get anchors, convert them to Polygons and rotate them.
|
||||
Polygons anchors = to_polygons(this->_anchor_regions);
|
||||
polygons_rotate(anchors, PI/2.0 - angle);
|
||||
if (angle == -1)
|
||||
angle = this->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);
|
||||
|
||||
/* 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));
|
||||
if (angle != -1) {
|
||||
|
||||
// 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);
|
||||
// Get anchors, convert them to Polygons and rotate them.
|
||||
Polygons anchors = to_polygons(this->_anchor_regions);
|
||||
polygons_rotate(anchors, PI/2.0 - angle);
|
||||
|
||||
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
|
||||
|
@ -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
@ -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);
|
||||
|
||||
|
@ -12,8 +12,9 @@
|
||||
namespace Slic3r {
|
||||
namespace EdgeGrid {
|
||||
|
||||
struct Grid
|
||||
class Grid
|
||||
{
|
||||
public:
|
||||
Grid();
|
||||
~Grid();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
@ -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
|
||||
|
@ -45,8 +45,7 @@ Fill* Fill::new_from_type(const std::string &type)
|
||||
Polylines Fill::fill_surface(const Surface *surface, const FillParams ¶ms)
|
||||
{
|
||||
// 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)
|
||||
|
@ -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();
|
||||
|
@ -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());
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)),
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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 = [
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user