Refactored Clipper wrapper functions

This commit is contained in:
Alessandro Ranellucci 2016-11-21 18:30:35 +01:00
parent be00f64243
commit 9fcd7f38de
27 changed files with 449 additions and 767 deletions

View File

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

View File

@ -30,12 +30,11 @@ BridgeDetector::BridgeDetector(const ExPolygon &_expolygon, const ExPolygonColle
{
/* outset our bridge by an arbitrary amout; we'll use this outer margin
for detecting anchors */
Polygons grown;
offset((Polygons)this->expolygon, &grown, this->extrusion_width);
Polygons grown = offset(this->expolygon, this->extrusion_width);
// 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
intersection(grown, this->lower_slices.contours(), &this->_edges);
this->_edges = intersection_pl(grown, this->lower_slices.contours());
#ifdef SLIC3R_DEBUG
printf(" bridge has %zu support(s)\n", this->_edges.size());
@ -43,7 +42,7 @@ BridgeDetector::BridgeDetector(const ExPolygon &_expolygon, const ExPolygonColle
// detect anchors as intersection between our bridge expolygon and the lower slices
// safety offset required to avoid Clipper from detecting empty intersection while Boost actually found some edges
intersection(grown, this->lower_slices, &this->_anchors, true);
this->_anchors = intersection_ex(grown, this->lower_slices, true);
/*
if (0) {
@ -65,8 +64,7 @@ BridgeDetector::detect_angle()
/* Outset the bridge expolygon by half the amount we used for detecting anchors;
we'll use this one to clip our test lines and be sure that their endpoints
are inside the anchors and not on their contours leading to false negatives. */
Polygons clip_area;
offset(this->expolygon, &clip_area, +this->extrusion_width/2);
Polygons clip_area = offset(this->expolygon, +this->extrusion_width/2);
/* we'll now try several directions using a rudimentary visibility check:
bridge in several directions and then sum the length of lines having both
@ -131,8 +129,7 @@ BridgeDetector::detect_angle()
for (coord_t y = bb.min.y; y <= bb.max.y; y += line_increment)
lines.push_back(Line(Point(bb.min.x, y), Point(bb.max.x, y)));
Lines clipped_lines;
intersection(lines, my_clip_area, &clipped_lines);
Lines clipped_lines = intersection_ln(lines, my_clip_area);
// remove any line not having both endpoints within anchors
for (size_t i = 0; i < clipped_lines.size(); ++i) {
@ -194,11 +191,11 @@ BridgeDetector::detect_angle()
return true;
}
void
BridgeDetector::coverage(double angle, Polygons* coverage) const
Polygons
BridgeDetector::coverage(double angle) const
{
if (angle == -1) angle = this->angle;
if (angle == -1) return;
if (angle == -1) return Polygons();
// Clone our expolygon and rotate it so that we work with vertical lines.
ExPolygon expolygon = this->expolygon;
@ -207,8 +204,7 @@ BridgeDetector::coverage(double angle, Polygons* coverage) const
/* 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(expolygon, &grown, this->extrusion_width/2.0);
ExPolygons grown = offset_ex(expolygon, this->extrusion_width/2.0);
// Compute trapezoids according to a vertical orientation
Polygons trapezoids;
@ -226,9 +222,7 @@ BridgeDetector::coverage(double angle, Polygons* coverage) const
Polygons covered;
for (Polygons::const_iterator trapezoid = trapezoids.begin(); trapezoid != trapezoids.end(); ++trapezoid) {
Lines lines = trapezoid->lines();
Lines supported;
intersection(lines, anchors, &supported);
Lines supported = intersection_ln(trapezoid->lines(), anchors);
// not nice, we need a more robust non-numeric check
for (size_t i = 0; i < supported.size(); ++i) {
@ -242,14 +236,13 @@ BridgeDetector::coverage(double angle, Polygons* coverage) const
}
// merge trapezoids and rotate them back
Polygons _coverage;
union_(covered, &_coverage);
Polygons _coverage = union_(covered);
for (Polygons::iterator p = _coverage.begin(); p != _coverage.end(); ++p)
p->rotate(-(PI/2.0 - angle), Point(0,0));
// intersect trapezoids with actual bridge area to remove extra margins
// and append it to result
intersection(_coverage, this->expolygon, coverage);
return intersection(_coverage, this->expolygon);
/*
if (0) {
@ -268,22 +261,14 @@ BridgeDetector::coverage(double angle, Polygons* coverage) const
*/
}
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
but would allow the entire bridge area to be bridged with detected angle
if supported too */
void
BridgeDetector::unsupported_edges(double angle, Polylines* unsupported) const
Polylines
BridgeDetector::unsupported_edges(double angle) const
{
if (angle == -1) angle = this->angle;
if (angle == -1) return;
if (angle == -1) return Polylines();
// get bridge edges (both contour and holes)
Polylines bridge_edges;
@ -293,10 +278,10 @@ BridgeDetector::unsupported_edges(double angle, Polylines* unsupported) const
}
// get unsupported edges
Polygons grown_lower;
offset(this->lower_slices, &grown_lower, +this->extrusion_width);
Polylines _unsupported;
diff(bridge_edges, grown_lower, &_unsupported);
Polylines _unsupported = diff_pl(
bridge_edges,
offset(this->lower_slices, +this->extrusion_width)
);
/* 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,
@ -304,13 +289,15 @@ BridgeDetector::unsupported_edges(double angle, Polylines* unsupported) const
extrusions would be anchored within such length (i.e. a slightly non-parallel bridging
direction might still benefit from anchors if long enough)
double angle_tolerance = PI / 180.0 * 5.0; */
Polylines unsupported;
for (Polylines::const_iterator polyline = _unsupported.begin(); polyline != _unsupported.end(); ++polyline) {
Lines lines = polyline->lines();
for (Lines::const_iterator line = lines.begin(); line != lines.end(); ++line) {
if (!Slic3r::Geometry::directions_parallel(line->direction(), angle))
unsupported->push_back(*line);
unsupported.push_back(*line);
}
}
return unsupported;
/*
if (0) {
@ -328,12 +315,4 @@ BridgeDetector::unsupported_edges(double angle, Polylines* unsupported) const
*/
}
Polylines
BridgeDetector::unsupported_edges(double angle) const
{
Polylines pp;
this->unsupported_edges(angle, &pp);
return pp;
}
}

View File

@ -18,9 +18,7 @@ class BridgeDetector {
BridgeDetector(const ExPolygon &_expolygon, 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;
private:

View File

@ -5,54 +5,53 @@ namespace Slic3r {
//-----------------------------------------------------------
// legacy code from Clipper documentation
void AddOuterPolyNodeToExPolygons(ClipperLib::PolyNode& polynode, Slic3r::ExPolygons* expolygons)
void AddOuterPolyNodeToExPolygons(ClipperLib::PolyNode& polynode, ExPolygons* expolygons)
{
size_t cnt = expolygons->size();
expolygons->resize(cnt + 1);
ClipperPath_to_Slic3rMultiPoint(polynode.Contour, &(*expolygons)[cnt].contour);
(*expolygons)[cnt].contour = ClipperPath_to_Slic3rMultiPoint<Polygon>(polynode.Contour);
(*expolygons)[cnt].holes.resize(polynode.ChildCount());
for (int i = 0; i < polynode.ChildCount(); ++i)
{
ClipperPath_to_Slic3rMultiPoint(polynode.Childs[i]->Contour, &(*expolygons)[cnt].holes[i]);
(*expolygons)[cnt].holes[i] = ClipperPath_to_Slic3rMultiPoint<Polygon>(polynode.Childs[i]->Contour);
//Add outer polygons contained by (nested within) holes ...
for (int j = 0; j < polynode.Childs[i]->ChildCount(); ++j)
AddOuterPolyNodeToExPolygons(*polynode.Childs[i]->Childs[j], expolygons);
}
}
void PolyTreeToExPolygons(ClipperLib::PolyTree& polytree, Slic3r::ExPolygons* expolygons)
ExPolygons
PolyTreeToExPolygons(ClipperLib::PolyTree& polytree)
{
expolygons->clear();
for (int i = 0; i < polytree.ChildCount(); ++i)
AddOuterPolyNodeToExPolygons(*polytree.Childs[i], expolygons);
ExPolygons retval;
for (int i = 0; i < polytree.ChildCount(); ++i)
AddOuterPolyNodeToExPolygons(*polytree.Childs[i], &retval);
return retval;
}
//-----------------------------------------------------------
template <class T>
void
ClipperPath_to_Slic3rMultiPoint(const ClipperLib::Path &input, T* output)
T
ClipperPath_to_Slic3rMultiPoint(const ClipperLib::Path &input)
{
output->points.clear();
for (ClipperLib::Path::const_iterator pit = input.begin(); pit != input.end(); ++pit) {
output->points.push_back(Slic3r::Point( (*pit).X, (*pit).Y ));
}
T retval;
for (ClipperLib::Path::const_iterator pit = input.begin(); pit != input.end(); ++pit)
retval.points.push_back(Point( (*pit).X, (*pit).Y ));
return retval;
}
template void ClipperPath_to_Slic3rMultiPoint<Slic3r::Polygon>(const ClipperLib::Path &input, Slic3r::Polygon* output);
template <class T>
void
ClipperPaths_to_Slic3rMultiPoints(const ClipperLib::Paths &input, T* output)
T
ClipperPaths_to_Slic3rMultiPoints(const ClipperLib::Paths &input)
{
output->clear();
for (ClipperLib::Paths::const_iterator it = input.begin(); it != input.end(); ++it) {
typename T::value_type p;
ClipperPath_to_Slic3rMultiPoint(*it, &p);
output->push_back(p);
}
T retval;
for (ClipperLib::Paths::const_iterator it = input.begin(); it != input.end(); ++it)
retval.push_back(ClipperPath_to_Slic3rMultiPoint<typename T::value_type>(*it));
return retval;
}
void
ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input, Slic3r::ExPolygons* output)
ExPolygons
ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input)
{
// init Clipper
ClipperLib::Clipper clipper;
@ -64,29 +63,26 @@ ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input, Slic3r::ExPolyg
clipper.Execute(ClipperLib::ctUnion, polytree, ClipperLib::pftEvenOdd, ClipperLib::pftEvenOdd); // offset results work with both EvenOdd and NonZero
// write to ExPolygons object
output->clear();
PolyTreeToExPolygons(polytree, output);
return PolyTreeToExPolygons(polytree);
}
void
Slic3rMultiPoint_to_ClipperPath(const Slic3r::MultiPoint &input, ClipperLib::Path* output)
ClipperLib::Path
Slic3rMultiPoint_to_ClipperPath(const MultiPoint &input)
{
output->clear();
for (Slic3r::Points::const_iterator pit = input.points.begin(); pit != input.points.end(); ++pit) {
output->push_back(ClipperLib::IntPoint( (*pit).x, (*pit).y ));
}
ClipperLib::Path retval;
for (Points::const_iterator pit = input.points.begin(); pit != input.points.end(); ++pit)
retval.push_back(ClipperLib::IntPoint( (*pit).x, (*pit).y ));
return retval;
}
template <class T>
void
Slic3rMultiPoints_to_ClipperPaths(const T &input, ClipperLib::Paths* output)
ClipperLib::Paths
Slic3rMultiPoints_to_ClipperPaths(const T &input)
{
output->clear();
for (typename T::const_iterator it = input.begin(); it != input.end(); ++it) {
ClipperLib::Path p;
Slic3rMultiPoint_to_ClipperPath(*it, &p);
output->push_back(p);
}
ClipperLib::Paths retval;
for (typename T::const_iterator it = input.begin(); it != input.end(); ++it)
retval.push_back(Slic3rMultiPoint_to_ClipperPath(*it));
return retval;
}
void
@ -100,13 +96,12 @@ scaleClipperPolygons(ClipperLib::Paths &polygons, const double scale)
}
}
void
offset(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float delta,
ClipperLib::Paths
_offset(const Polygons &polygons, const float delta,
double scale, ClipperLib::JoinType joinType, double miterLimit)
{
// read input
ClipperLib::Paths input;
Slic3rMultiPoints_to_ClipperPaths(polygons, &input);
ClipperLib::Paths input = Slic3rMultiPoints_to_ClipperPaths(polygons);
// scale input
scaleClipperPolygons(input, scale);
@ -119,40 +114,20 @@ offset(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float
co.MiterLimit = miterLimit;
}
co.AddPaths(input, joinType, ClipperLib::etClosedPolygon);
co.Execute(*retval, (delta*scale));
ClipperLib::Paths retval;
co.Execute(retval, (delta*scale));
// unscale output
scaleClipperPolygons(*retval, 1/scale);
scaleClipperPolygons(retval, 1/scale);
return retval;
}
void
offset(const Slic3r::Polygons &polygons, Slic3r::Polygons* retval, const float delta,
double scale, ClipperLib::JoinType joinType, double miterLimit)
{
// perform offset
ClipperLib::Paths output;
offset(polygons, &output, delta, scale, joinType, miterLimit);
// convert into ExPolygons
ClipperPaths_to_Slic3rMultiPoints(output, retval);
}
Slic3r::Polygons
offset(const Slic3r::Polygons &polygons, const float delta,
double scale, ClipperLib::JoinType joinType, double miterLimit)
{
Slic3r::Polygons pp;
offset(polygons, &pp, delta, scale, joinType, miterLimit);
return pp;
}
void
offset(const Slic3r::Polylines &polylines, ClipperLib::Paths* retval, const float delta,
ClipperLib::Paths
_offset(const Polylines &polylines, const float delta,
double scale, ClipperLib::JoinType joinType, double miterLimit)
{
// read input
ClipperLib::Paths input;
Slic3rMultiPoints_to_ClipperPaths(polylines, &input);
ClipperLib::Paths input = Slic3rMultiPoints_to_ClipperPaths(polylines);
// scale input
scaleClipperPolygons(input, scale);
@ -165,82 +140,78 @@ offset(const Slic3r::Polylines &polylines, ClipperLib::Paths* retval, const floa
co.MiterLimit = miterLimit;
}
co.AddPaths(input, joinType, ClipperLib::etOpenButt);
co.Execute(*retval, (delta*scale));
ClipperLib::Paths retval;
co.Execute(retval, (delta*scale));
// unscale output
scaleClipperPolygons(*retval, 1/scale);
scaleClipperPolygons(retval, 1/scale);
return retval;
}
void
offset(const Slic3r::Polylines &polylines, Slic3r::Polygons* retval, const float delta,
Polygons
offset(const Polygons &polygons, const float delta,
double scale, ClipperLib::JoinType joinType, double miterLimit)
{
// perform offset
ClipperLib::Paths output;
offset(polylines, &output, delta, scale, joinType, miterLimit);
ClipperLib::Paths output = _offset(polygons, delta, scale, joinType, miterLimit);
// convert into ExPolygons
ClipperPaths_to_Slic3rMultiPoints(output, retval);
return ClipperPaths_to_Slic3rMultiPoints<Polygons>(output);
}
void
offset(const Slic3r::Surface &surface, Slic3r::Surfaces* retval, const float delta,
Polygons
offset(const Polylines &polylines, const float delta,
double scale, ClipperLib::JoinType joinType, double miterLimit)
{
// perform offset
Slic3r::ExPolygons expp;
offset(surface.expolygon, &expp, delta, scale, joinType, miterLimit);
ClipperLib::Paths output = _offset(polylines, delta, scale, joinType, miterLimit);
// convert into ExPolygons
return ClipperPaths_to_Slic3rMultiPoints<Polygons>(output);
}
Surfaces
offset(const Surface &surface, const float delta,
double scale, ClipperLib::JoinType joinType, double miterLimit)
{
// perform offset
ExPolygons expp = offset_ex(surface.expolygon, delta, scale, joinType, miterLimit);
// clone the input surface for each expolygon we got
retval->clear();
retval->reserve(expp.size());
Surfaces retval;
retval.reserve(expp.size());
for (ExPolygons::iterator it = expp.begin(); it != expp.end(); ++it) {
Surface s = surface; // clone
s.expolygon = *it;
retval->push_back(s);
retval.push_back(s);
}
return retval;
}
void
offset(const Slic3r::Polygons &polygons, Slic3r::ExPolygons* retval, const float delta,
ExPolygons
offset_ex(const Polygons &polygons, const float delta,
double scale, ClipperLib::JoinType joinType, double miterLimit)
{
// perform offset
ClipperLib::Paths output;
offset(polygons, &output, delta, scale, joinType, miterLimit);
ClipperLib::Paths output = _offset(polygons, delta, scale, joinType, miterLimit);
// convert into ExPolygons
ClipperPaths_to_Slic3rExPolygons(output, retval);
return ClipperPaths_to_Slic3rExPolygons(output);
}
Slic3r::ExPolygons
offset_ex(const Slic3r::Polygons &polygons, const float delta,
ExPolygons
offset_ex(const ExPolygons &expolygons, const float delta,
double scale, ClipperLib::JoinType joinType, double miterLimit)
{
Slic3r::ExPolygons expp;
offset(polygons, &expp, delta, scale, joinType, miterLimit);
return expp;
return offset_ex(to_polygons(expolygons), delta, scale, joinType, miterLimit);
}
Slic3r::ExPolygons
offset_ex(const Slic3r::ExPolygons &expolygons, const float delta,
double scale, ClipperLib::JoinType joinType, double miterLimit)
{
Slic3r::Polygons pp;
for (Slic3r::ExPolygons::const_iterator ex = expolygons.begin(); ex != expolygons.end(); ++ex) {
Slic3r::Polygons pp2 = *ex;
pp.insert(pp.end(), pp2.begin(), pp2.end());
}
return offset_ex(pp, delta, scale, joinType, miterLimit);
}
void
offset2(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float delta1,
const float delta2, const double scale, const ClipperLib::JoinType joinType, const double miterLimit)
ClipperLib::Paths
_offset2(const Polygons &polygons, const float delta1, const float delta2,
const double scale, const ClipperLib::JoinType joinType, const double miterLimit)
{
// read input
ClipperLib::Paths input;
Slic3rMultiPoints_to_ClipperPaths(polygons, &input);
ClipperLib::Paths input = Slic3rMultiPoints_to_ClipperPaths(polygons);
// scale input
scaleClipperPolygons(input, scale);
@ -261,62 +232,44 @@ offset2(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float
// perform second offset
co.Clear();
co.AddPaths(output1, joinType, ClipperLib::etClosedPolygon);
co.Execute(*retval, (delta2*scale));
ClipperLib::Paths retval;
co.Execute(retval, (delta2*scale));
// unscale output
scaleClipperPolygons(*retval, 1/scale);
scaleClipperPolygons(retval, 1/scale);
return retval;
}
void
offset2(const Slic3r::Polygons &polygons, Slic3r::Polygons* retval, const float delta1,
const float delta2, const double scale, const ClipperLib::JoinType joinType, const double miterLimit)
Polygons
offset2(const Polygons &polygons, const float delta1, const float delta2,
const double scale, const ClipperLib::JoinType joinType, const double miterLimit)
{
// perform offset
ClipperLib::Paths output;
offset2(polygons, &output, delta1, delta2, scale, joinType, miterLimit);
ClipperLib::Paths output = _offset2(polygons, delta1, delta2, scale, joinType, miterLimit);
// convert into ExPolygons
ClipperPaths_to_Slic3rMultiPoints(output, retval);
return ClipperPaths_to_Slic3rMultiPoints<Polygons>(output);
}
Slic3r::Polygons
offset2(const Slic3r::Polygons &polygons, const float delta1,
const float delta2, const double scale, const ClipperLib::JoinType joinType, const double miterLimit)
{
Slic3r::Polygons pp;
offset2(polygons, &pp, delta1, delta2, scale, joinType, miterLimit);
return pp;
}
void
offset2(const Slic3r::Polygons &polygons, Slic3r::ExPolygons* retval, const float delta1,
const float delta2, const double scale, const ClipperLib::JoinType joinType, const double miterLimit)
ExPolygons
offset2_ex(const Polygons &polygons, const float delta1, const float delta2,
const double scale, const ClipperLib::JoinType joinType, const double miterLimit)
{
// perform offset
ClipperLib::Paths output;
offset2(polygons, &output, delta1, delta2, scale, joinType, miterLimit);
ClipperLib::Paths output = _offset2(polygons, delta1, delta2, scale, joinType, miterLimit);
// convert into ExPolygons
ClipperPaths_to_Slic3rExPolygons(output, retval);
}
Slic3r::ExPolygons
offset2_ex(const Slic3r::Polygons &polygons, const float delta1,
const float delta2, const double scale, const ClipperLib::JoinType joinType, const double miterLimit)
{
Slic3r::ExPolygons expp;
offset2(polygons, &expp, delta1, delta2, scale, joinType, miterLimit);
return expp;
return ClipperPaths_to_Slic3rExPolygons(output);
}
template <class T>
void _clipper_do(const ClipperLib::ClipType clipType, const Slic3r::Polygons &subject,
const Slic3r::Polygons &clip, T* retval, const ClipperLib::PolyFillType fillType, const bool safety_offset_)
T
_clipper_do(const ClipperLib::ClipType clipType, const Polygons &subject,
const Polygons &clip, const ClipperLib::PolyFillType fillType, const bool safety_offset_)
{
// read input
ClipperLib::Paths input_subject, input_clip;
Slic3rMultiPoints_to_ClipperPaths(subject, &input_subject);
Slic3rMultiPoints_to_ClipperPaths(clip, &input_clip);
ClipperLib::Paths input_subject = Slic3rMultiPoints_to_ClipperPaths(subject);
ClipperLib::Paths input_clip = Slic3rMultiPoints_to_ClipperPaths(clip);
// perform safety offset
if (safety_offset_) {
@ -333,20 +286,22 @@ void _clipper_do(const ClipperLib::ClipType clipType, const Slic3r::Polygons &su
// add polygons
clipper.AddPaths(input_subject, ClipperLib::ptSubject, true);
clipper.AddPaths(input_clip, ClipperLib::ptClip, true);
clipper.AddPaths(input_clip, ClipperLib::ptClip, true);
// perform operation
clipper.Execute(clipType, *retval, fillType, fillType);
T retval;
clipper.Execute(clipType, retval, fillType, fillType);
return retval;
}
void _clipper_do(const ClipperLib::ClipType clipType, const Slic3r::Polylines &subject,
const Slic3r::Polygons &clip, ClipperLib::PolyTree* retval, const ClipperLib::PolyFillType fillType,
ClipperLib::PolyTree
_clipper_do(const ClipperLib::ClipType clipType, const Polylines &subject,
const Polygons &clip, const ClipperLib::PolyFillType fillType,
const bool safety_offset_)
{
// read input
ClipperLib::Paths input_subject, input_clip;
Slic3rMultiPoints_to_ClipperPaths(subject, &input_subject);
Slic3rMultiPoints_to_ClipperPaths(clip, &input_clip);
ClipperLib::Paths input_subject = Slic3rMultiPoints_to_ClipperPaths(subject);
ClipperLib::Paths input_clip = Slic3rMultiPoints_to_ClipperPaths(clip);
// perform safety offset
if (safety_offset_) safety_offset(&input_clip);
@ -360,285 +315,133 @@ void _clipper_do(const ClipperLib::ClipType clipType, const Slic3r::Polylines &s
clipper.AddPaths(input_clip, ClipperLib::ptClip, true);
// perform operation
clipper.Execute(clipType, *retval, fillType, fillType);
ClipperLib::PolyTree retval;
clipper.Execute(clipType, retval, fillType, fillType);
return retval;
}
void _clipper(ClipperLib::ClipType clipType, const Slic3r::Polygons &subject,
const Slic3r::Polygons &clip, Slic3r::Polygons* retval, bool safety_offset_)
Polygons
_clipper(ClipperLib::ClipType clipType, const Polygons &subject,
const Polygons &clip, bool safety_offset_)
{
// perform operation
ClipperLib::Paths output;
_clipper_do<ClipperLib::Paths>(clipType, subject, clip, &output, ClipperLib::pftNonZero, safety_offset_);
ClipperLib::Paths output = _clipper_do<ClipperLib::Paths>(clipType, subject, clip, ClipperLib::pftNonZero, safety_offset_);
// convert into Polygons
ClipperPaths_to_Slic3rMultiPoints(output, retval);
return ClipperPaths_to_Slic3rMultiPoints<Polygons>(output);
}
void _clipper(ClipperLib::ClipType clipType, const Slic3r::Polygons &subject,
const Slic3r::Polygons &clip, Slic3r::ExPolygons* retval, bool safety_offset_)
ExPolygons
_clipper_ex(ClipperLib::ClipType clipType, const Polygons &subject,
const Polygons &clip, bool safety_offset_)
{
// perform operation
ClipperLib::PolyTree polytree;
_clipper_do<ClipperLib::PolyTree>(clipType, subject, clip, &polytree, ClipperLib::pftNonZero, safety_offset_);
ClipperLib::PolyTree polytree = _clipper_do<ClipperLib::PolyTree>(clipType, subject, clip, ClipperLib::pftNonZero, safety_offset_);
// convert into ExPolygons
PolyTreeToExPolygons(polytree, retval);
return PolyTreeToExPolygons(polytree);
}
void _clipper(ClipperLib::ClipType clipType, const Slic3r::Polylines &subject,
const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_)
Polylines
_clipper_pl(ClipperLib::ClipType clipType, const Polylines &subject,
const Polygons &clip, bool safety_offset_)
{
// perform operation
ClipperLib::PolyTree polytree;
_clipper_do(clipType, subject, clip, &polytree, ClipperLib::pftNonZero, safety_offset_);
ClipperLib::PolyTree polytree = _clipper_do(clipType, subject, clip, ClipperLib::pftNonZero, safety_offset_);
// convert into Polylines
ClipperLib::Paths output;
ClipperLib::PolyTreeToPaths(polytree, output);
ClipperPaths_to_Slic3rMultiPoints(output, retval);
return ClipperPaths_to_Slic3rMultiPoints<Polylines>(output);
}
void _clipper(ClipperLib::ClipType clipType, const Slic3r::Lines &subject,
const Slic3r::Polygons &clip, Slic3r::Lines* retval, bool safety_offset_)
{
// convert Lines to Polylines
Slic3r::Polylines polylines;
polylines.reserve(subject.size());
for (Slic3r::Lines::const_iterator line = subject.begin(); line != subject.end(); ++line)
polylines.push_back(*line);
// perform operation
_clipper(clipType, polylines, clip, &polylines, safety_offset_);
// convert Polylines to Lines
for (Slic3r::Polylines::const_iterator polyline = polylines.begin(); polyline != polylines.end(); ++polyline)
retval->push_back(*polyline);
}
void _clipper(ClipperLib::ClipType clipType, const Slic3r::Polygons &subject,
const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_)
Polylines
_clipper_pl(ClipperLib::ClipType clipType, const Polygons &subject,
const Polygons &clip, bool safety_offset_)
{
// transform input polygons into polylines
Slic3r::Polylines polylines;
Polylines polylines;
polylines.reserve(subject.size());
for (Slic3r::Polygons::const_iterator polygon = subject.begin(); polygon != subject.end(); ++polygon)
for (Polygons::const_iterator polygon = subject.begin(); polygon != subject.end(); ++polygon)
polylines.push_back(*polygon); // implicit call to split_at_first_point()
// perform clipping
_clipper(clipType, polylines, clip, retval, safety_offset_);
Polylines retval = _clipper_pl(clipType, polylines, clip, safety_offset_);
/* If the split_at_first_point() call above happens to split the polygon inside the clipping area
we would get two consecutive polylines instead of a single one, so we go through them in order
to recombine continuous polylines. */
for (size_t i = 0; i < retval->size(); ++i) {
for (size_t j = i+1; j < retval->size(); ++j) {
if ((*retval)[i].points.back().coincides_with((*retval)[j].points.front())) {
for (size_t i = 0; i < retval.size(); ++i) {
for (size_t j = i+1; j < retval.size(); ++j) {
if (retval[i].points.back().coincides_with(retval[j].points.front())) {
/* If last point of i coincides with first point of j,
append points of j to i and delete j */
(*retval)[i].points.insert((*retval)[i].points.end(), (*retval)[j].points.begin()+1, (*retval)[j].points.end());
retval->erase(retval->begin() + j);
retval[i].points.insert(retval[i].points.end(), retval[j].points.begin()+1, retval[j].points.end());
retval.erase(retval.begin() + j);
--j;
} else if ((*retval)[i].points.front().coincides_with((*retval)[j].points.back())) {
} else if (retval[i].points.front().coincides_with(retval[j].points.back())) {
/* If first point of i coincides with last point of j,
prepend points of j to i and delete j */
(*retval)[i].points.insert((*retval)[i].points.begin(), (*retval)[j].points.begin(), (*retval)[j].points.end()-1);
retval->erase(retval->begin() + j);
retval[i].points.insert(retval[i].points.begin(), retval[j].points.begin(), retval[j].points.end()-1);
retval.erase(retval.begin() + j);
--j;
} else if ((*retval)[i].points.front().coincides_with((*retval)[j].points.front())) {
} else if (retval[i].points.front().coincides_with(retval[j].points.front())) {
/* Since Clipper does not preserve orientation of polylines,
also check the case when first point of i coincides with first point of j. */
(*retval)[j].reverse();
(*retval)[i].points.insert((*retval)[i].points.begin(), (*retval)[j].points.begin(), (*retval)[j].points.end()-1);
retval->erase(retval->begin() + j);
retval[j].reverse();
retval[i].points.insert(retval[i].points.begin(), retval[j].points.begin(), retval[j].points.end()-1);
retval.erase(retval.begin() + j);
--j;
} else if ((*retval)[i].points.back().coincides_with((*retval)[j].points.back())) {
} else if (retval[i].points.back().coincides_with(retval[j].points.back())) {
/* Since Clipper does not preserve orientation of polylines,
also check the case when last point of i coincides with last point of j. */
(*retval)[j].reverse();
(*retval)[i].points.insert((*retval)[i].points.end(), (*retval)[j].points.begin()+1, (*retval)[j].points.end());
retval->erase(retval->begin() + j);
retval[j].reverse();
retval[i].points.insert(retval[i].points.end(), retval[j].points.begin()+1, retval[j].points.end());
retval.erase(retval.begin() + j);
--j;
}
}
}
}
template <class SubjectType, class ResultType>
void diff(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_)
{
_clipper(ClipperLib::ctDifference, subject, clip, retval, safety_offset_);
}
template void diff<Slic3r::Polygons, Slic3r::ExPolygons>(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::ExPolygons* retval, bool safety_offset_);
template void diff<Slic3r::Polygons, Slic3r::Polygons>(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::Polygons* retval, bool safety_offset_);
template void diff<Slic3r::Polygons, Slic3r::Polylines>(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_);
template void diff<Slic3r::Polylines, Slic3r::Polylines>(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_);
template void diff<Slic3r::Lines, Slic3r::Lines>(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, Slic3r::Lines* retval, bool safety_offset_);
template <class SubjectType, class ResultType>
void diff(const SubjectType &subject, const Slic3r::ExPolygons &clip, ResultType* retval, bool safety_offset_)
{
Slic3r::Polygons pp;
for (Slic3r::ExPolygons::const_iterator ex = clip.begin(); ex != clip.end(); ++ex) {
Slic3r::Polygons ppp = *ex;
pp.insert(pp.end(), ppp.begin(), ppp.end());
}
diff(subject, pp, retval, safety_offset_);
}
template void diff<Slic3r::Polygons, Slic3r::ExPolygons>(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, Slic3r::ExPolygons* retval, bool safety_offset_);
template <class ResultType>
void diff(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, ResultType* retval, bool safety_offset_)
{
Slic3r::Polygons pp;
for (Slic3r::ExPolygons::const_iterator ex = subject.begin(); ex != subject.end(); ++ex) {
Slic3r::Polygons ppp = *ex;
pp.insert(pp.end(), ppp.begin(), ppp.end());
}
diff(pp, clip, retval, safety_offset_);
}
Slic3r::Polygons
diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_)
{
Slic3r::Polygons pp;
diff(subject, clip, &pp, safety_offset_);
return pp;
}
template <class SubjectType, class ClipType>
Slic3r::ExPolygons
diff_ex(const SubjectType &subject, const ClipType &clip, bool safety_offset_)
{
Slic3r::ExPolygons expp;
diff(subject, clip, &expp, safety_offset_);
return expp;
}
template Slic3r::ExPolygons diff_ex<Slic3r::Polygons, Slic3r::Polygons>(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_);
template Slic3r::ExPolygons diff_ex<Slic3r::Polygons, Slic3r::ExPolygons>(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_);
template Slic3r::ExPolygons diff_ex<Slic3r::ExPolygons, Slic3r::ExPolygons>(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_);
template <class SubjectType, class ResultType>
void intersection(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_)
{
_clipper(ClipperLib::ctIntersection, subject, clip, retval, safety_offset_);
}
template void intersection<Slic3r::Polygons, Slic3r::ExPolygons>(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::ExPolygons* retval, bool safety_offset_);
template void intersection<Slic3r::Polygons, Slic3r::Polygons>(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::Polygons* retval, bool safety_offset_);
template void intersection<Slic3r::Polygons, Slic3r::Polylines>(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_);
template void intersection<Slic3r::Polylines, Slic3r::Polylines>(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_);
template void intersection<Slic3r::Lines, Slic3r::Lines>(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, Slic3r::Lines* retval, bool safety_offset_);
template <class SubjectType>
SubjectType intersection(const SubjectType &subject, const Slic3r::Polygons &clip, bool safety_offset_)
{
SubjectType pp;
intersection(subject, clip, &pp, safety_offset_);
return pp;
}
template Slic3r::Polygons intersection<Slic3r::Polygons>(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_);
template Slic3r::Polylines intersection<Slic3r::Polylines>(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool safety_offset_);
template Slic3r::Lines intersection<Slic3r::Lines>(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, bool safety_offset_);
Slic3r::ExPolygons
intersection_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_)
{
Slic3r::ExPolygons expp;
intersection(subject, clip, &expp, safety_offset_);
return expp;
}
template <class SubjectType>
bool intersects(const SubjectType &subject, const Slic3r::Polygons &clip, bool safety_offset_)
{
SubjectType retval;
intersection(subject, clip, &retval, safety_offset_);
return !retval.empty();
}
template bool intersects<Slic3r::Polygons>(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_);
template bool intersects<Slic3r::Polylines>(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool safety_offset_);
template bool intersects<Slic3r::Lines>(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, bool safety_offset_);
void xor_(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::ExPolygons* retval,
bool safety_offset_)
{
_clipper(ClipperLib::ctXor, subject, clip, retval, safety_offset_);
}
template <class T>
void union_(const Slic3r::Polygons &subject, T* retval, bool safety_offset_)
{
Slic3r::Polygons p;
_clipper(ClipperLib::ctUnion, subject, p, retval, safety_offset_);
}
template void union_<Slic3r::ExPolygons>(const Slic3r::Polygons &subject, Slic3r::ExPolygons* retval, bool safety_offset_);
template void union_<Slic3r::Polygons>(const Slic3r::Polygons &subject, Slic3r::Polygons* retval, bool safety_offset_);
Slic3r::Polygons
union_(const Slic3r::Polygons &subject, bool safety_offset)
{
Polygons pp;
union_(subject, &pp, safety_offset);
return pp;
}
Slic3r::ExPolygons
union_ex(const Slic3r::Polygons &subject, bool safety_offset)
{
ExPolygons expp;
union_(subject, &expp, safety_offset);
return expp;
}
Slic3r::ExPolygons
union_ex(const Slic3r::Surfaces &subject, bool safety_offset)
{
Polygons pp;
for (Slic3r::Surfaces::const_iterator s = subject.begin(); s != subject.end(); ++s) {
Polygons spp = *s;
pp.insert(pp.end(), spp.begin(), spp.end());
}
return union_ex(pp, safety_offset);
}
void union_(const Slic3r::Polygons &subject1, const Slic3r::Polygons &subject2, Slic3r::Polygons* retval, bool safety_offset)
{
Polygons pp = subject1;
pp.insert(pp.end(), subject2.begin(), subject2.end());
union_(pp, retval, safety_offset);
}
Slic3r::Polygons
union_(const Slic3r::ExPolygons &subject1, const Slic3r::ExPolygons &subject2, bool safety_offset)
{
Polygons pp;
for (Slic3r::ExPolygons::const_iterator it = subject1.begin(); it != subject1.end(); ++it) {
Polygons spp = *it;
pp.insert(pp.end(), spp.begin(), spp.end());
}
for (Slic3r::ExPolygons::const_iterator it = subject2.begin(); it != subject2.end(); ++it) {
Polygons spp = *it;
pp.insert(pp.end(), spp.begin(), spp.end());
}
Polygons retval;
union_(pp, &retval, safety_offset);
return retval;
}
void union_pt(const Slic3r::Polygons &subject, ClipperLib::PolyTree* retval, bool safety_offset_)
Lines
_clipper_ln(ClipperLib::ClipType clipType, const Lines &subject, const Polygons &clip,
bool safety_offset_)
{
Slic3r::Polygons clip;
_clipper_do<ClipperLib::PolyTree>(ClipperLib::ctUnion, subject, clip, retval, ClipperLib::pftEvenOdd, safety_offset_);
// convert Lines to Polylines
Polylines polylines;
polylines.reserve(subject.size());
for (Lines::const_iterator line = subject.begin(); line != subject.end(); ++line)
polylines.push_back(*line);
// perform operation
polylines = _clipper_pl(clipType, polylines, clip, safety_offset_);
// convert Polylines to Lines
Lines retval;
for (Polylines::const_iterator polyline = polylines.begin(); polyline != polylines.end(); ++polyline)
retval.push_back(*polyline);
return retval;
}
void union_pt_chained(const Slic3r::Polygons &subject, Slic3r::Polygons* retval, bool safety_offset_)
ClipperLib::PolyTree
union_pt(const Polygons &subject, bool safety_offset_)
{
ClipperLib::PolyTree pt;
union_pt(subject, &pt, safety_offset_);
traverse_pt(pt.Childs, retval);
return _clipper_do<ClipperLib::PolyTree>(ClipperLib::ctUnion, subject, Polygons(), ClipperLib::pftEvenOdd, safety_offset_);
}
static void traverse_pt(ClipperLib::PolyNodes &nodes, Slic3r::Polygons* retval)
Polygons
union_pt_chained(const Polygons &subject, bool safety_offset_)
{
ClipperLib::PolyTree polytree = union_pt(subject, safety_offset_);
Polygons retval;
traverse_pt(polytree.Childs, &retval);
return retval;
}
static void traverse_pt(ClipperLib::PolyNodes &nodes, Polygons* retval)
{
/* use a nearest neighbor search to order these children
TODO: supply start_near to chained_path() too? */
@ -660,19 +463,19 @@ static void traverse_pt(ClipperLib::PolyNodes &nodes, Slic3r::Polygons* retval)
// traverse the next depth
traverse_pt((*it)->Childs, retval);
Polygon p;
ClipperPath_to_Slic3rMultiPoint((*it)->Contour, &p);
Polygon p = ClipperPath_to_Slic3rMultiPoint<Polygon>((*it)->Contour);
retval->push_back(p);
if ((*it)->IsHole()) retval->back().reverse(); // ccw
}
}
void simplify_polygons(const Slic3r::Polygons &subject, Slic3r::Polygons* retval, bool preserve_collinear)
Polygons
simplify_polygons(const Polygons &subject, bool preserve_collinear)
{
// convert into Clipper polygons
ClipperLib::Paths input_subject, output;
Slic3rMultiPoints_to_ClipperPaths(subject, &input_subject);
ClipperLib::Paths input_subject = Slic3rMultiPoints_to_ClipperPaths(subject);
ClipperLib::Paths output;
if (preserve_collinear) {
ClipperLib::Clipper c;
c.PreserveCollinear(true);
@ -684,21 +487,18 @@ void simplify_polygons(const Slic3r::Polygons &subject, Slic3r::Polygons* retval
}
// convert into Slic3r polygons
ClipperPaths_to_Slic3rMultiPoints(output, retval);
return ClipperPaths_to_Slic3rMultiPoints<Polygons>(output);
}
void simplify_polygons(const Slic3r::Polygons &subject, Slic3r::ExPolygons* retval, bool preserve_collinear)
ExPolygons
simplify_polygons_ex(const Polygons &subject, bool preserve_collinear)
{
if (!preserve_collinear) {
Polygons polygons;
simplify_polygons(subject, &polygons, preserve_collinear);
union_(polygons, retval);
return;
return union_ex(simplify_polygons(subject, preserve_collinear));
}
// convert into Clipper polygons
ClipperLib::Paths input_subject;
Slic3rMultiPoints_to_ClipperPaths(subject, &input_subject);
ClipperLib::Paths input_subject = Slic3rMultiPoints_to_ClipperPaths(subject);
ClipperLib::PolyTree polytree;
@ -709,7 +509,7 @@ void simplify_polygons(const Slic3r::Polygons &subject, Slic3r::ExPolygons* retv
c.Execute(ClipperLib::ctUnion, polytree, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
// convert into ExPolygons
PolyTreeToExPolygons(polytree, retval);
return PolyTreeToExPolygons(polytree);
}
void safety_offset(ClipperLib::Paths* paths)

View File

@ -22,22 +22,19 @@ 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);
T ClipperPaths_to_Slic3rMultiPoints(const ClipperLib::Paths &input);
Slic3r::ExPolygons ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input);
void scaleClipperPolygons(ClipperLib::Paths &polygons, const double scale);
// offset Polygons
void offset(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float delta,
double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
double miterLimit = 3);
void offset(const Slic3r::Polygons &polygons, Slic3r::Polygons* retval, const float delta,
ClipperLib::Paths _offset(const Slic3r::Polygons &polygons, const float delta,
double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
double miterLimit = 3);
Slic3r::Polygons offset(const Slic3r::Polygons &polygons, const float delta,
@ -45,19 +42,16 @@ Slic3r::Polygons offset(const Slic3r::Polygons &polygons, const float delta,
double miterLimit = 3);
// offset Polylines
void offset(const Slic3r::Polylines &polylines, ClipperLib::Paths* retval, const float delta,
ClipperLib::Paths _offset(const Slic3r::Polylines &polylines, const float delta,
double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtSquare,
double miterLimit = 3);
void offset(const Slic3r::Polylines &polylines, Slic3r::Polygons* retval, const float delta,
Slic3r::Polygons offset(const Slic3r::Polylines &polylines, const float delta,
double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtSquare,
double miterLimit = 3);
void offset(const Slic3r::Surface &surface, Slic3r::Surfaces* retval, const float delta,
Slic3r::Surfaces offset(const Slic3r::Surface &surface, const float delta,
double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtSquare,
double miterLimit = 3);
void offset(const Slic3r::Polygons &polygons, Slic3r::ExPolygons* retval, const float delta,
double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
double miterLimit = 3);
Slic3r::ExPolygons offset_ex(const Slic3r::Polygons &polygons, const float delta,
double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
double miterLimit = 3);
@ -65,78 +59,159 @@ Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygons &expolygons, const float d
double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
double miterLimit = 3);
void offset2(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float delta1,
const float delta2, double scale = 100000, 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, double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
double miterLimit = 3);
Slic3r::Polygons offset2(const Slic3r::Polygons &polygons, const float delta1,
const float delta2, double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
double miterLimit = 3);
void offset2(const Slic3r::Polygons &polygons, Slic3r::ExPolygons* retval, const float delta1,
const float delta2, double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
double miterLimit = 3);
Slic3r::ExPolygons offset2_ex(const Slic3r::Polygons &polygons, const float delta1,
const float delta2, double scale = 100000, 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(ClipperLib::ClipType clipType, const Slic3r::Polylines &subject,
const Slic3r::Polygons &clip, Slic3r::Polylines* retval);
void _clipper(ClipperLib::ClipType clipType, const Slic3r::Lines &subject,
const Slic3r::Polygons &clip, Slic3r::Lines* retval);
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);
// diff
inline Slic3r::Polygons
diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
{
return _clipper(ClipperLib::ctDifference, subject, clip, safety_offset_);
}
template <class SubjectType, class ClipType>
Slic3r::ExPolygons diff_ex(const SubjectType &subject, const ClipType &clip, bool safety_offset_ = false);
inline Slic3r::ExPolygons
diff_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
{
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 Slic3r::ExPolygons
diff_ex(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_ = false)
{
return _clipper_ex(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::Polygons
diff(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_ = false)
{
return _clipper(ClipperLib::ctDifference, to_polygons(subject), to_polygons(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::Polygons &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::Polylines
diff_pl(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
{
return _clipper_pl(ClipperLib::ctDifference, subject, clip, safety_offset_);
}
void xor_(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::ExPolygons* retval,
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_);
}
template <class T>
void union_(const Slic3r::Polygons &subject, T* retval, bool safety_offset_ = false);
// 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_);
}
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::ExPolygons
intersection_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
{
return _clipper_ex(ClipperLib::ctIntersection, subject, clip, 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
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_);
}
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);
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)
{
return _clipper_pl(ClipperLib::ctIntersection, subject, clip, safety_offset_);
}
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_);
}
// union
inline Slic3r::Polygons
union_(const Slic3r::Polygons &subject, bool safety_offset_ = false)
{
return _clipper(ClipperLib::ctUnion, subject, Slic3r::Polygons(), safety_offset_);
}
inline Slic3r::Polygons
union_(const Slic3r::Polygons &subject, const Slic3r::Polygons &subject2, bool safety_offset_ = false)
{
return _clipper(ClipperLib::ctUnion, subject, subject2, safety_offset_);
}
inline Slic3r::ExPolygons
union_ex(const Slic3r::Polygons &subject, bool safety_offset_ = false)
{
return _clipper_ex(ClipperLib::ctUnion, subject, Slic3r::Polygons(), safety_offset_);
}
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_);
}
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);
static void traverse_pt(ClipperLib::PolyNodes &nodes, Slic3r::Polygons* retval);
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);
/* 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);

View File

@ -90,9 +90,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
@ -152,8 +150,7 @@ ExPolygon::simplify_p(double tolerance) const
p.points.pop_back();
pp.push_back(p);
}
simplify_polygons(pp, &pp);
return pp;
return simplify_polygons(pp);
}
ExPolygons
@ -346,8 +343,7 @@ ExPolygon::get_trapezoids2(Polygons* polygons) const
poly[3].y = bb.max.y;
// intersect with this expolygon
Polygons trapezoids;
intersection<Polygons,Polygons>(poly, *this, &trapezoids);
Polygons trapezoids = intersection(poly, *this);
// append results to return value
polygons->insert(polygons->end(), trapezoids.begin(), trapezoids.end());
@ -384,10 +380,7 @@ 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 = simplify_polygons_ex(*this, true);
for (ExPolygons::const_iterator ex = expp.begin(); ex != expp.end(); ++ex) {
// contour
@ -440,8 +433,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
@ -505,4 +497,15 @@ ExPolygon::dump_perl() const
return ret.str();
}
Polygons
to_polygons(const ExPolygons &expolygons)
{
Slic3r::Polygons pp;
for (ExPolygons::const_iterator ex = expolygons.begin(); ex != expolygons.end(); ++ex) {
Slic3r::Polygons ppp = *ex;
pp.insert(pp.end(), ppp.begin(), ppp.end());
}
return pp;
}
}

View File

@ -45,6 +45,8 @@ class ExPolygon
std::string dump_perl() const;
};
Polygons to_polygons(const ExPolygons &expolygons);
}
// start Boost

View File

@ -36,8 +36,7 @@ void
ExtrusionPath::intersect_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const
{
// perform clipping
Polylines clipped;
intersection<Polylines,Polylines>(this->polyline, collection, &clipped);
Polylines clipped = intersection_pl(this->polyline, collection);
return this->_inflate_collection(clipped, retval);
}
@ -45,8 +44,7 @@ void
ExtrusionPath::subtract_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const
{
// perform clipping
Polylines clipped;
diff<Polylines,Polylines>(this->polyline, collection, &clipped);
Polylines clipped = diff_pl(this->polyline, collection);
return this->_inflate_collection(clipped, retval);
}
@ -113,9 +111,7 @@ ExtrusionPath::_inflate_collection(const Polylines &polylines, ExtrusionEntityCo
Polygons
ExtrusionPath::grow() const
{
Polygons pp;
offset(this->polyline, &pp, +scale_(this->width/2));
return pp;
return offset(this->polyline, +scale_(this->width/2));
}
ExtrusionLoop*

View File

@ -283,11 +283,8 @@ GCode::change_layer(const Layer &layer)
this->first_layer = (layer.id() == 0);
// avoid computing islands and overhangs if they're not needed
if (this->config.avoid_crossing_perimeters) {
ExPolygons islands;
union_(layer.slices, &islands, true);
this->avoid_crossing_perimeters.init_layer_mp(islands);
}
if (this->config.avoid_crossing_perimeters)
this->avoid_crossing_perimeters.init_layer_mp(union_ex(layer.slices, true));
std::string gcode;
if (this->layer_count > 0) {

View File

@ -149,20 +149,6 @@ deg2rad(double angle)
return PI * angle / 180.0;
}
void
simplify_polygons(const Polygons &polygons, double tolerance, Polygons* retval)
{
Polygons pp;
for (Polygons::const_iterator it = polygons.begin(); it != polygons.end(); ++it) {
Polygon p = *it;
p.points.push_back(p.points.front());
p.points = MultiPoint::_douglas_peucker(p.points, tolerance);
p.points.pop_back();
pp.push_back(p);
}
Slic3r::simplify_polygons(pp, retval);
}
double
linint(double value, double oldmin, double oldmax, double newmin, double newmax)
{

View File

@ -23,7 +23,6 @@ template<class T> bool contains(const std::vector<T> &vector, const Point &point
double rad2deg(double angle);
double rad2deg_dir(double angle);
double deg2rad(double angle);
void simplify_polygons(const Polygons &polygons, double tolerance, Polygons* retval);
class ArrangeItem {
public:

View File

@ -110,7 +110,7 @@ Layer::make_slices()
Polygons region_slices_p = (*layerm)->slices;
slices_p.insert(slices_p.end(), region_slices_p.begin(), region_slices_p.end());
}
union_(slices_p, &slices);
slices = union_ex(slices_p);
}
this->slices.expolygons.clear();
@ -229,8 +229,8 @@ Layer::make_perimeters()
if (!fill_surfaces.surfaces.empty()) {
for (LayerRegionPtrs::iterator l = layerms.begin(); l != layerms.end(); ++l) {
ExPolygons expp = intersection_ex(
fill_surfaces,
(*l)->slices
(Polygons) fill_surfaces,
(Polygons) (*l)->slices
);
(*l)->fill_surfaces.surfaces.clear();

View File

@ -45,9 +45,8 @@ LayerRegion::flow(FlowRole role, bool bridge, double width) const
void
LayerRegion::merge_slices()
{
ExPolygons expp;
// without safety offset, artifacts are generated (GH #2494)
union_(this->slices, &expp, true);
ExPolygons expp = union_ex((Polygons)this->slices, true);
this->slices.surfaces.clear();
this->slices.surfaces.reserve(expp.size());

View File

@ -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(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(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(Line(from, pp[result]), this->island).size() > 1) {
// discard result
pp.erase(pp.begin() + result);
} else {

View File

@ -343,8 +343,7 @@ PerimeterGenerator::_traverse_loops(const PerimeterGeneratorLoops &loops,
&& !(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);
Polylines polylines = intersection_pl(loop->polygon, this->_lower_slices_p);
for (Polylines::const_iterator polyline = polylines.begin(); polyline != polylines.end(); ++polyline) {
ExtrusionPath path(role);
@ -360,8 +359,7 @@ PerimeterGenerator::_traverse_loops(const PerimeterGeneratorLoops &loops,
// 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);
Polylines polylines = diff_pl(loop->polygon, this->_lower_slices_p);
for (Polylines::const_iterator polyline = polylines.begin(); polyline != polylines.end(); ++polyline) {
ExtrusionPath path(erOverhangPerimeter);

View File

@ -86,17 +86,13 @@ Polygon::equally_spaced_points(double distance) const
double
Polygon::area() const
{
ClipperLib::Path p;
Slic3rMultiPoint_to_ClipperPath(*this, &p);
return ClipperLib::Area(p);
return ClipperLib::Area(Slic3rMultiPoint_to_ClipperPath(*this));
}
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
@ -157,10 +153,7 @@ Polygon::simplify(double tolerance) const
Polygon p(MultiPoint::_douglas_peucker(points, tolerance));
p.points.pop_back();
Polygons pp;
pp.push_back(p);
simplify_polygons(pp, &pp);
return pp;
return simplify_polygons(p);
}
void

View File

@ -607,20 +607,16 @@ 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, 1, jtRound, scale_(0.1));
convex_hull = grown_hull.front();
}
convex_hull = offset(convex_hull, scale_(this->config.extruder_clearance_radius.value)/2, 1, 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())
throw PrintValidationException("Some objects are too close; your extruder will collide with them.");
union_(a, p, &a);
a = union_(a, p);
}
}
}

View File

@ -429,7 +429,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);
// build the new collection of fill_surfaces
{

View File

@ -54,4 +54,15 @@ Surface::is_bridge() const
|| this->surface_type == stInternalBridge;
}
Polygons
to_polygons(const Surfaces &surfaces)
{
Slic3r::Polygons pp;
for (Surfaces::const_iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
Slic3r::Polygons ppp = *s;
pp.insert(pp.end(), ppp.begin(), ppp.end());
}
return pp;
}
}

View File

@ -34,6 +34,8 @@ class Surface
typedef std::vector<Surface> Surfaces;
typedef std::vector<Surface*> SurfacesPtr;
Polygons to_polygons(const Surfaces &surfaces);
}
#endif

View File

@ -390,10 +390,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
@ -848,14 +845,13 @@ TriangleMeshSlicer::make_expolygons(const Polygons &loops, ExPolygons* slices)
if (area[*loop_idx] > +EPSILON) {
p_slices.push_back(*loop);
} 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)
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_DEBUG
size_t holes_count = 0;

View File

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

View File

@ -8,6 +8,40 @@
%package{Slic3r::Geometry::Clipper};
Polygons offset(Polygons polygons, float delta, double scale = CLIPPER_OFFSET_SCALE,
ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
ExPolygons offset_ex(Polygons polygons, float delta, double scale = CLIPPER_OFFSET_SCALE,
ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
Polygons offset2(Polygons polygons, float delta1, float delta2, double scale = CLIPPER_OFFSET_SCALE,
ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
ExPolygons offset2_ex(Polygons polygons, float delta1, float delta2, double scale = CLIPPER_OFFSET_SCALE,
ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
Polygons diff(Polygons subject, Polygons clip, bool safety_offset = false);
ExPolygons diff_ex(Polygons subject, Polygons clip, bool safety_offset = false);
Polylines diff_pl(Polylines subject, Polygons clip);
Polygons intersection(Polygons subject, Polygons clip, bool safety_offset = false);
ExPolygons intersection_ex(Polygons subject, Polygons clip, bool safety_offset = false);
Polylines intersection_pl(Polylines subject, Polygons clip);
%name{intersection_ppl} Polylines intersection_pl(Polygons subject, Polygons clip);
%name{union} Polygons union_(Polygons subject, bool safety_offset = false);
ExPolygons union_ex(Polygons subject, bool safety_offset = false);
Polygons union_pt_chained(Polygons subject, bool safety_offset = false);
Polygons simplify_polygons(Polygons subject);
%{
IV
@ -21,188 +55,15 @@ _constant()
RETVAL = ix;
OUTPUT: RETVAL
Polygons
offset(polygons, delta, scale = CLIPPER_OFFSET_SCALE, joinType = ClipperLib::jtMiter, miterLimit = 3)
Polygons polygons
const float delta
double scale
ClipperLib::JoinType joinType
double miterLimit
CODE:
offset(polygons, &RETVAL, delta, scale, joinType, miterLimit);
OUTPUT:
RETVAL
ExPolygons
offset_ex(polygons, delta, scale = CLIPPER_OFFSET_SCALE, joinType = ClipperLib::jtMiter, miterLimit = 3)
Polygons polygons
const float delta
double scale
ClipperLib::JoinType joinType
double miterLimit
CODE:
offset(polygons, &RETVAL, delta, scale, joinType, miterLimit);
OUTPUT:
RETVAL
Polygons
offset2(polygons, delta1, delta2, scale = CLIPPER_OFFSET_SCALE, joinType = ClipperLib::jtMiter, miterLimit = 3)
Polygons polygons
const float delta1
const float delta2
double scale
ClipperLib::JoinType joinType
double miterLimit
CODE:
offset2(polygons, &RETVAL, delta1, delta2, scale, joinType, miterLimit);
OUTPUT:
RETVAL
ExPolygons
offset2_ex(polygons, delta1, delta2, scale = CLIPPER_OFFSET_SCALE, joinType = ClipperLib::jtMiter, miterLimit = 3)
Polygons polygons
const float delta1
const float delta2
double scale
ClipperLib::JoinType joinType
double miterLimit
CODE:
offset2(polygons, &RETVAL, delta1, delta2, scale, joinType, miterLimit);
OUTPUT:
RETVAL
Polygons
diff(subject, clip, safety_offset = false)
Polygons subject
Polygons clip
bool safety_offset
CODE:
diff(subject, clip, &RETVAL, safety_offset);
OUTPUT:
RETVAL
ExPolygons
diff_ex(subject, clip, safety_offset = false)
Polygons subject
Polygons clip
bool safety_offset
CODE:
diff(subject, clip, &RETVAL, safety_offset);
OUTPUT:
RETVAL
Polylines
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);
OUTPUT:
RETVAL
Polygons
intersection(subject, clip, safety_offset = false)
Polygons subject
Polygons clip
bool safety_offset
CODE:
intersection(subject, clip, &RETVAL, safety_offset);
OUTPUT:
RETVAL
ExPolygons
intersection_ex(subject, clip, safety_offset = false)
Polygons subject
Polygons clip
bool safety_offset
CODE:
intersection(subject, clip, &RETVAL, safety_offset);
OUTPUT:
RETVAL
Polylines
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);
OUTPUT:
RETVAL
Polygons
union(subject, safety_offset = false)
Polygons subject
bool safety_offset
CODE:
union_(subject, &RETVAL, safety_offset);
OUTPUT:
RETVAL
ExPolygons
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);
ClipperLib::PolyTree polytree = union_pt(subject, safety_offset);
RETVAL = polynode_children_2_perl(polytree);
OUTPUT:
RETVAL
Polygons
union_pt_chained(subject, safety_offset = false)
Polygons subject
bool safety_offset
CODE:
union_pt_chained(subject, &RETVAL, safety_offset);
OUTPUT:
RETVAL
Polygons
simplify_polygons(subject)
Polygons subject
CODE:
simplify_polygons(subject, &RETVAL);
OUTPUT:
RETVAL
%}

View File

@ -81,15 +81,6 @@ deg2rad(angle)
OUTPUT:
RETVAL
Polygons
simplify_polygons(polygons, tolerance)
Polygons polygons
double tolerance
CODE:
Slic3r::Geometry::simplify_polygons(polygons, tolerance, &RETVAL);
OUTPUT:
RETVAL
IV
_constant()

View File

@ -86,7 +86,7 @@ Polyline::grow(delta, scale = CLIPPER_OFFSET_SCALE, joinType = ClipperLib::jtSqu
ClipperLib::JoinType joinType
double miterLimit
CODE:
offset(*THIS, &RETVAL, delta, scale, joinType, miterLimit);
RETVAL = offset(*THIS, delta, scale, joinType, miterLimit);
OUTPUT:
RETVAL

View File

@ -89,7 +89,7 @@ Surface::offset(delta, scale = CLIPPER_OFFSET_SCALE, joinType = ClipperLib::jtMi
ClipperLib::JoinType joinType
double miterLimit
CODE:
offset(*THIS, &RETVAL, delta, scale, joinType, miterLimit);
RETVAL = offset(*THIS, delta, scale, joinType, miterLimit);
OUTPUT:
RETVAL

View File

@ -198,7 +198,8 @@
%typemap{LayerPtrs*};
%typemap{SupportLayerPtrs*};
%typemap{ClipperLib::JoinType}{simple};
%typemap{ClipperLib::PolyFillType}{simple};
%typemap{Axis}{parsed}{
%cpp_type{Axis};
%precall_code{%