Update Clipper to 6.1.2

This commit is contained in:
Alessandro Ranellucci 2013-12-24 12:40:46 +01:00
parent 1a690589a8
commit bd133d9434
6 changed files with 1064 additions and 1091 deletions

View file

@ -932,7 +932,7 @@ sub write_gcode {
# append full config # append full config
print $fh "\n"; print $fh "\n";
foreach my $opt_key (sort @{$self->config->get_keys}) { foreach my $opt_key (sort @{$self->config->get_keys}) {
next if @{$Slic3r::Config::Options->{$opt_key}{shortcut}}; next if $Slic3r::Config::Options->{$opt_key}{shortcut};
printf $fh "; %s = %s\n", $opt_key, $self->config->serialize($opt_key); printf $fh "; %s = %s\n", $opt_key, $self->config->serialize($opt_key);
} }
} }

View file

@ -9,6 +9,7 @@ BEGIN {
use lib "$FindBin::Bin/../lib"; use lib "$FindBin::Bin/../lib";
} }
use List::Util qw(sum);
use Slic3r; use Slic3r;
use Slic3r::Geometry::Clipper qw(intersection_ex union_ex diff_ex); use Slic3r::Geometry::Clipper qw(intersection_ex union_ex diff_ex);
@ -33,7 +34,7 @@ use Slic3r::Geometry::Clipper qw(intersection_ex union_ex diff_ex);
]; ];
my $intersection = intersection_ex([ $square, $hole_in_square ], [ $square2 ]); my $intersection = intersection_ex([ $square, $hole_in_square ], [ $square2 ]);
is_deeply [ map $_->pp, @$intersection ], [[ is sum(map $_->area, @$intersection), Slic3r::ExPolygon->new(
[ [
[20, 18], [20, 18],
[10, 18], [10, 18],
@ -46,7 +47,7 @@ use Slic3r::Geometry::Clipper qw(intersection_ex union_ex diff_ex);
[16, 14], [16, 14],
[14, 14], [14, 14],
], ],
]], 'hole is preserved after intersection'; )->area, 'hole is preserved after intersection';
} }
#========================================================== #==========================================================
@ -62,7 +63,8 @@ use Slic3r::Geometry::Clipper qw(intersection_ex union_ex diff_ex);
'union of two ccw and one cw is a contour with no holes'; 'union of two ccw and one cw is a contour with no holes';
my $diff = diff_ex([ $contour1, $contour2 ], [ $hole ]); my $diff = diff_ex([ $contour1, $contour2 ], [ $hole ]);
is_deeply [ map $_->pp, @$diff ], [[ [ [40,40], [0,40], [0,0], [40,0] ], [ [15,25], [25,25], [25,15], [15,15] ] ]], is sum(map $_->area, @$diff),
Slic3r::ExPolygon->new([ [40,40], [0,40], [0,0], [40,0] ], [ [15,25], [25,25], [25,15], [15,15] ])->area,
'difference of a cw from two ccw is a contour with one hole'; 'difference of a cw from two ccw is a contour with one hole';
} }

View file

@ -106,15 +106,21 @@ offset(const Slic3r::Polygons &polygons, ClipperLib::Paths &retval, const float
double scale, ClipperLib::JoinType joinType, double miterLimit) double scale, ClipperLib::JoinType joinType, double miterLimit)
{ {
// read input // read input
ClipperLib::Paths* input = new ClipperLib::Paths(); ClipperLib::Paths input;
Slic3rMultiPoints_to_ClipperPaths(polygons, *input); Slic3rMultiPoints_to_ClipperPaths(polygons, input);
// scale input // scale input
scaleClipperPolygons(*input, scale); scaleClipperPolygons(input, scale);
// perform offset // perform offset
ClipperLib::OffsetPaths(*input, retval, (delta*scale), joinType, ClipperLib::etClosed, miterLimit); ClipperLib::ClipperOffset co;
delete input; if (joinType == jtRound) {
co.ArcTolerance = miterLimit;
} else {
co.MiterLimit = miterLimit;
}
co.AddPaths(input, joinType, ClipperLib::etClosedPolygon);
co.Execute(retval, (delta*scale));
// unscale output // unscale output
scaleClipperPolygons(retval, 1/scale); scaleClipperPolygons(retval, 1/scale);
@ -125,12 +131,11 @@ offset(const Slic3r::Polygons &polygons, Slic3r::Polygons &retval, const float d
double scale, ClipperLib::JoinType joinType, double miterLimit) double scale, ClipperLib::JoinType joinType, double miterLimit)
{ {
// perform offset // perform offset
ClipperLib::Paths* output = new ClipperLib::Paths(); ClipperLib::Paths output;
offset(polygons, *output, delta, scale, joinType, miterLimit); offset(polygons, output, delta, scale, joinType, miterLimit);
// convert into ExPolygons // convert into ExPolygons
ClipperPaths_to_Slic3rMultiPoints(*output, retval); ClipperPaths_to_Slic3rMultiPoints(output, retval);
delete output;
} }
void void
@ -138,15 +143,21 @@ offset(const Slic3r::Polylines &polylines, ClipperLib::Paths &retval, const floa
double scale, ClipperLib::JoinType joinType, double miterLimit) double scale, ClipperLib::JoinType joinType, double miterLimit)
{ {
// read input // read input
ClipperLib::Paths* input = new ClipperLib::Paths(); ClipperLib::Paths input;
Slic3rMultiPoints_to_ClipperPaths(polylines, *input); Slic3rMultiPoints_to_ClipperPaths(polylines, input);
// scale input // scale input
scaleClipperPolygons(*input, scale); scaleClipperPolygons(input, scale);
// perform offset // perform offset
ClipperLib::OffsetPaths(*input, retval, (delta*scale), joinType, ClipperLib::etButt, miterLimit); ClipperLib::ClipperOffset co;
delete input; if (joinType == jtRound) {
co.ArcTolerance = miterLimit;
} else {
co.MiterLimit = miterLimit;
}
co.AddPaths(input, joinType, ClipperLib::etOpenButt);
co.Execute(retval, (delta*scale));
// unscale output // unscale output
scaleClipperPolygons(retval, 1/scale); scaleClipperPolygons(retval, 1/scale);
@ -201,20 +212,29 @@ offset2(const Slic3r::Polygons &polygons, ClipperLib::Paths &retval, const float
const float delta2, const double scale, const ClipperLib::JoinType joinType, const double miterLimit) const float delta2, const double scale, const ClipperLib::JoinType joinType, const double miterLimit)
{ {
// read input // read input
ClipperLib::Paths* input = new ClipperLib::Paths(); ClipperLib::Paths input;
Slic3rMultiPoints_to_ClipperPaths(polygons, *input); Slic3rMultiPoints_to_ClipperPaths(polygons, input);
// scale input // scale input
scaleClipperPolygons(*input, scale); scaleClipperPolygons(input, scale);
// prepare ClipperOffset object
ClipperLib::ClipperOffset co;
if (joinType == jtRound) {
co.ArcTolerance = miterLimit;
} else {
co.MiterLimit = miterLimit;
}
// perform first offset // perform first offset
ClipperLib::Paths* output1 = new ClipperLib::Paths(); ClipperLib::Paths output1;
ClipperLib::OffsetPaths(*input, *output1, (delta1*scale), joinType, ClipperLib::etClosed, miterLimit); co.AddPaths(input, joinType, ClipperLib::etClosedPolygon);
delete input; co.Execute(output1, (delta1*scale));
// perform second offset // perform second offset
ClipperLib::OffsetPaths(*output1, retval, (delta2*scale), joinType, ClipperLib::etClosed, miterLimit); co.Clear();
delete output1; co.AddPaths(output1, joinType, ClipperLib::etClosedPolygon);
co.Execute(retval, (delta2*scale));
// unscale output // unscale output
scaleClipperPolygons(retval, 1/scale); scaleClipperPolygons(retval, 1/scale);
@ -444,7 +464,10 @@ void safety_offset(ClipperLib::Paths* &subject)
// perform offset (delta = scale 1e-05) // perform offset (delta = scale 1e-05)
ClipperLib::Paths* retval = new ClipperLib::Paths(); ClipperLib::Paths* retval = new ClipperLib::Paths();
ClipperLib::OffsetPaths(*subject, *retval, 10.0 * CLIPPER_OFFSET_SCALE, ClipperLib::jtMiter, ClipperLib::etClosed, 2); ClipperLib::ClipperOffset co;
co.MiterLimit = 2;
co.AddPaths(*subject, ClipperLib::jtMiter, ClipperLib::etClosedPolygon);
co.Execute(*retval, 10.0 * CLIPPER_OFFSET_SCALE);
// unscale output // unscale output
scaleClipperPolygons(*retval, 1.0/CLIPPER_OFFSET_SCALE); scaleClipperPolygons(*retval, 1.0/CLIPPER_OFFSET_SCALE);

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,8 @@
/******************************************************************************* /*******************************************************************************
* * * *
* Author : Angus Johnson * * Author : Angus Johnson *
* Version : 6.0.0 * * Version : 6.1.2 *
* Date : 30 October 2013 * * Date : 15 December 2013 *
* Website : http://www.angusj.com * * Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2013 * * Copyright : Angus Johnson 2010-2013 *
* * * *
@ -34,7 +34,7 @@
#ifndef clipper_hpp #ifndef clipper_hpp
#define clipper_hpp #define clipper_hpp
#define CLIPPER_VERSION "6.0.0" #define CLIPPER_VERSION "6.1.2"
//use_int32: When enabled 32bit ints are used instead of 64bit ints. This //use_int32: When enabled 32bit ints are used instead of 64bit ints. This
//improve performance but coordinate values are limited to the range +/- 46340 //improve performance but coordinate values are limited to the range +/- 46340
@ -46,9 +46,8 @@
//use_lines: Enables line clipping. Adds a very minor cost to performance. //use_lines: Enables line clipping. Adds a very minor cost to performance.
#define use_lines #define use_lines
//When enabled, code developed with earlier versions of Clipper //use_deprecated: Enables support for the obsolete OffsetPaths() function
//(ie prior to ver 6) should compile without changes. //which has been replace with the ClipperOffset class.
//In a future update, this compatability code will be removed.
//#define use_deprecated //#define use_deprecated
#include <vector> #include <vector>
@ -108,12 +107,6 @@ std::ostream& operator <<(std::ostream &s, const IntPoint &p);
std::ostream& operator <<(std::ostream &s, const Path &p); std::ostream& operator <<(std::ostream &s, const Path &p);
std::ostream& operator <<(std::ostream &s, const Paths &p); std::ostream& operator <<(std::ostream &s, const Paths &p);
#ifdef use_deprecated
typedef signed long long long64; //backward compatibility only
typedef Path Polygon;
typedef Paths Polygons;
#endif
struct DoublePoint struct DoublePoint
{ {
double X; double X;
@ -127,6 +120,13 @@ struct DoublePoint
typedef void (*TZFillCallback)(IntPoint& z1, IntPoint& z2, IntPoint& pt); typedef void (*TZFillCallback)(IntPoint& z1, IntPoint& z2, IntPoint& pt);
#endif #endif
enum InitOptions {ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4};
enum JoinType {jtSquare, jtRound, jtMiter};
enum EndType {etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound};
#ifdef use_deprecated
enum EndType_ {etClosed, etButt = 2, etSquare, etRound};
#endif
class PolyNode; class PolyNode;
typedef std::vector< PolyNode* > PolyNodes; typedef std::vector< PolyNode* > PolyNodes;
@ -142,11 +142,14 @@ public:
bool IsOpen() const; bool IsOpen() const;
int ChildCount() const; int ChildCount() const;
private: private:
bool m_IsOpen;
PolyNode* GetNextSiblingUp() const;
unsigned Index; //node index in Parent.Childs unsigned Index; //node index in Parent.Childs
bool m_IsOpen;
JoinType m_jointype;
EndType m_endtype;
PolyNode* GetNextSiblingUp() const;
void AddChild(PolyNode& child); void AddChild(PolyNode& child);
friend class Clipper; //to access Index friend class Clipper; //to access Index
friend class ClipperOffset;
}; };
class PolyTree: public PolyNode class PolyTree: public PolyNode
@ -161,24 +164,14 @@ private:
friend class Clipper; //to access AllNodes friend class Clipper; //to access AllNodes
}; };
enum InitOptions {ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4};
enum JoinType {jtSquare, jtRound, jtMiter};
enum EndType {etClosed, etButt, etSquare, etRound};
bool Orientation(const Path &poly); bool Orientation(const Path &poly);
double Area(const Path &poly); double Area(const Path &poly);
#ifdef use_deprecated #ifdef use_deprecated
void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys, void OffsetPaths(const Paths &in_polys, Paths &out_polys,
double delta, JoinType jointype = jtSquare, double limit = 0, bool autoFix = true); double delta, JoinType jointype, EndType_ endtype, double limit = 0);
void PolyTreeToPolygons(const PolyTree& polytree, Paths& paths);
void ReversePolygon(Path& p);
void ReversePolygons(Paths& p);
#endif #endif
void OffsetPaths(const Paths &in_polys, Paths &out_polys,
double delta, JoinType jointype, EndType endtype, double limit = 0);
void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType = pftEvenOdd); void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType = pftEvenOdd); void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
void SimplifyPolygons(Paths &polys, PolyFillType fillType = pftEvenOdd); void SimplifyPolygons(Paths &polys, PolyFillType fillType = pftEvenOdd);
@ -188,8 +181,8 @@ void CleanPolygon(Path& poly, double distance = 1.415);
void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance = 1.415); void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance = 1.415);
void CleanPolygons(Paths& polys, double distance = 1.415); void CleanPolygons(Paths& polys, double distance = 1.415);
void MinkowkiSum(const Path& poly, const Path& path, Paths& solution, bool isClosed); void MinkowskiSum(const Path& poly, const Path& path, Paths& solution, bool isClosed);
void MinkowkiDiff(const Path& poly, const Path& path, Paths& solution, bool isClosed); void MinkowskiDiff(const Path& poly, const Path& path, Paths& solution, bool isClosed);
void PolyTreeToPaths(const PolyTree& polytree, Paths& paths); void PolyTreeToPaths(const PolyTree& polytree, Paths& paths);
void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths); void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths);
@ -215,6 +208,8 @@ struct Join;
typedef std::vector < OutRec* > PolyOutList; typedef std::vector < OutRec* > PolyOutList;
typedef std::vector < TEdge* > EdgeList; typedef std::vector < TEdge* > EdgeList;
typedef std::vector < Join* > JoinList; typedef std::vector < Join* > JoinList;
typedef std::vector < IntersectNode* > IntersectList;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -228,12 +223,6 @@ public:
virtual ~ClipperBase(); virtual ~ClipperBase();
bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed); bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed);
bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed); bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed);
#ifdef use_deprecated
bool AddPolygon(const Path &pg, PolyType PolyTyp);
bool AddPolygons(const Paths &ppg, PolyType PolyTyp);
#endif
virtual void Clear(); virtual void Clear();
IntRect GetBounds(); IntRect GetBounds();
bool PreserveCollinear() {return m_PreserveCollinear;}; bool PreserveCollinear() {return m_PreserveCollinear;};
@ -243,6 +232,7 @@ protected:
TEdge* AddBoundsToLML(TEdge *e, bool IsClosed); TEdge* AddBoundsToLML(TEdge *e, bool IsClosed);
void PopLocalMinima(); void PopLocalMinima();
virtual void Reset(); virtual void Reset();
TEdge* ProcessBound(TEdge* E, bool IsClockwise);
void InsertLocalMinima(LocalMinima *newLm); void InsertLocalMinima(LocalMinima *newLm);
void DoMinimaLML(TEdge* E1, TEdge* E2, bool IsClosed); void DoMinimaLML(TEdge* E1, TEdge* E2, bool IsClosed);
TEdge* DescendToMin(TEdge *&E); TEdge* DescendToMin(TEdge *&E);
@ -285,11 +275,11 @@ private:
PolyOutList m_PolyOuts; PolyOutList m_PolyOuts;
JoinList m_Joins; JoinList m_Joins;
JoinList m_GhostJoins; JoinList m_GhostJoins;
IntersectList m_IntersectList;
ClipType m_ClipType; ClipType m_ClipType;
std::set< cInt, std::greater<cInt> > m_Scanbeam; std::set< cInt, std::greater<cInt> > m_Scanbeam;
TEdge *m_ActiveEdges; TEdge *m_ActiveEdges;
TEdge *m_SortedEdges; TEdge *m_SortedEdges;
IntersectNode *m_IntersectNodes;
bool m_ExecuteLocked; bool m_ExecuteLocked;
PolyFillType m_ClipFillType; PolyFillType m_ClipFillType;
PolyFillType m_SubjFillType; PolyFillType m_SubjFillType;
@ -330,7 +320,6 @@ private:
void DisposeAllOutRecs(); void DisposeAllOutRecs();
void DisposeOutRec(PolyOutList::size_type index); void DisposeOutRec(PolyOutList::size_type index);
bool ProcessIntersections(const cInt botY, const cInt topY); bool ProcessIntersections(const cInt botY, const cInt topY);
void InsertIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt);
void BuildIntersectList(const cInt botY, const cInt topY); void BuildIntersectList(const cInt botY, const cInt topY);
void ProcessIntersectList(); void ProcessIntersectList();
void ProcessEdgesAtTopOfScanbeam(const cInt topY); void ProcessEdgesAtTopOfScanbeam(const cInt topY);
@ -341,12 +330,13 @@ private:
bool FixupIntersectionOrder(); bool FixupIntersectionOrder();
void FixupOutPolygon(OutRec &outrec); void FixupOutPolygon(OutRec &outrec);
bool IsHole(TEdge *e); bool IsHole(TEdge *e);
bool FindOwnerFromSplitRecs(OutRec &outRec, OutRec *&currOrfl);
void FixHoleLinkage(OutRec &outrec); void FixHoleLinkage(OutRec &outrec);
void AddJoin(OutPt *op1, OutPt *op2, const IntPoint offPt); void AddJoin(OutPt *op1, OutPt *op2, const IntPoint offPt);
void ClearJoins(); void ClearJoins();
void ClearGhostJoins(); void ClearGhostJoins();
void AddGhostJoin(OutPt *op, const IntPoint offPt); void AddGhostJoin(OutPt *op, const IntPoint offPt);
bool JoinPoints(const Join *j, OutPt *&p1, OutPt *&p2); bool JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2);
void JoinCommonEdges(); void JoinCommonEdges();
void DoSimplePolygons(); void DoSimplePolygons();
void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec); void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec);
@ -357,6 +347,37 @@ private:
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
class ClipperOffset
{
public:
ClipperOffset(double miterLimit = 2.0, double roundPrecision = 0.25);
~ClipperOffset();
void AddPath(const Path& path, JoinType joinType, EndType endType);
void AddPaths(const Paths& paths, JoinType joinType, EndType endType);
void Execute(Paths& solution, double delta);
void Execute(PolyTree& solution, double delta);
void Clear();
double MiterLimit;
double ArcTolerance;
private:
Paths m_destPolys;
Path m_srcPoly;
Path m_destPoly;
std::vector<DoublePoint> m_normals;
double m_delta, m_sinA, m_sin, m_cos;
double m_miterLim, m_StepsPerRad;
IntPoint m_lowest;
PolyNode m_polyNodes;
void FixOrientations();
void DoOffset(double delta);
void OffsetPoint(int j, int& k, JoinType jointype);
void DoSquare(int j, int k);
void DoMiter(int j, int k, double r);
void DoRound(int j, int k);
};
//------------------------------------------------------------------------------
class clipperException : public std::exception class clipperException : public std::exception
{ {
public: public:

View file

@ -43,10 +43,10 @@ my $expolygon = Slic3r::ExPolygon->new($square, $hole_in_square);
[95, 95], [95, 95],
[205, 95], [205, 95],
], [ ], [
[145, 145],
[145, 155], [145, 155],
[155, 155], [155, 155],
[155, 145], [155, 145],
[145, 145],
] ], 'offset_ex'; ] ], 'offset_ex';
} }
@ -58,10 +58,10 @@ my $expolygon = Slic3r::ExPolygon->new($square, $hole_in_square);
[97, 97], [97, 97],
[203, 97], [203, 97],
], [ ], [
[143, 143],
[143, 157], [143, 157],
[157, 157], [157, 157],
[157, 143], [157, 143],
[143, 143],
] ], 'offset2_ex'; ] ], 'offset2_ex';
} }
@ -78,7 +78,7 @@ my $expolygon = Slic3r::ExPolygon->new($square, $hole_in_square);
[5000000, 5000000], [5000000, 5000000],
]); ]);
my $result = Slic3r::Geometry::Clipper::offset2_ex([ @$expolygon2 ], -1, +1); my $result = Slic3r::Geometry::Clipper::offset2_ex([ @$expolygon2 ], -1, +1);
is_deeply $result->[0]->pp, $expolygon2->pp, 'offset2_ex'; is $result->[0]->area, $expolygon2->area, 'offset2_ex';
} }
{ {