Update Clipper to 6.0.0

This commit is contained in:
Alessandro Ranellucci 2013-11-20 11:35:58 +01:00
parent d49052779f
commit 50c0081d25
16 changed files with 2941 additions and 1816 deletions

View File

@ -293,6 +293,7 @@ sub make_perimeters {
my @p = map $_->medial_axis($pspacing), @thin_walls;
my @paths = ();
for my $p (@p) {
next if $p->length <= $pspacing * 2;
my %params = (
role => EXTR_ROLE_EXTERNAL_PERIMETER,
flow_spacing => $self->perimeter_flow->spacing,

View File

@ -31,7 +31,7 @@ sub point_on_left {
sub grow {
my $self = shift;
return Slic3r::Polyline->new(@$self[0,1,0])->grow(@_);
return Slic3r::Polyline->new(@$self)->grow(@_);
}
1;

View File

@ -35,20 +35,6 @@ sub simplify {
return __PACKAGE__->new(@$simplified);
}
sub grow {
my $self = shift;
my ($distance, $scale, $joinType, $miterLimit) = @_;
$joinType //= JT_SQUARE; # we override this one
$scale //= 100000; # we init these because we can't pass undef
$miterLimit //= 3;
my @points = @$self;
return @{Slic3r::Geometry::Clipper::offset(
[ Slic3r::Polygon->new(@points, CORE::reverse @points[1..($#points-1)]) ],
$distance, $scale, $joinType, $miterLimit,
)};
}
sub clip_with_polygon {
my $self = shift;
my ($polygon) = @_;

View File

@ -652,10 +652,10 @@ sub make_brim {
if (@{ $object->support_layers }) {
my $support_layer0 = $object->support_layers->[0];
push @object_islands,
(map $_->polyline->grow($grow_distance), @{$support_layer0->support_fills})
(map @{$_->polyline->grow($grow_distance)}, @{$support_layer0->support_fills})
if $support_layer0->support_fills;
push @object_islands,
(map $_->polyline->grow($grow_distance), @{$support_layer0->support_interface_fills})
(map @{$_->polyline->grow($grow_distance)}, @{$support_layer0->support_interface_fills})
if $support_layer0->support_interface_fills;
}
foreach my $copy (@{$object->copies}) {
@ -666,7 +666,7 @@ sub make_brim {
# if brim touches skirt, make it around skirt too
# TODO: calculate actual skirt width (using each extruder's flow in multi-extruder setups)
if ($Slic3r::Config->skirt_distance + (($Slic3r::Config->skirts - 1) * $flow->spacing) <= $Slic3r::Config->brim_width) {
push @islands, map $_->split_at_first_point->polyline->grow($grow_distance), @{$self->skirt};
push @islands, map @{$_->split_at_first_point->polyline->grow($grow_distance)}, @{$self->skirt};
}
my @loops = ();

View File

@ -258,6 +258,10 @@ sub make_perimeters {
# only add the perimeter if there's an intersection with the collapsed area
last CYCLE if !@{ intersection($diff, $hypothetical_perimeter) };
use Slic3r::SVG;
Slic3r::SVG::output("extra.svg",
expolygons => union_ex(intersection($diff, $hypothetical_perimeter)),
);exit;
Slic3r::debugf " adding one more perimeter at layer %d\n", $layer_id;
$slice->extra_perimeters($extra_perimeters);
}

View File

@ -480,7 +480,7 @@ sub generate_toolpaths {
# solution should be found to achieve both goals
$contact_infill = diff(
$contact,
[ map $_->grow($circle_radius*1.1), @loops ],
[ map @{$_->grow($circle_radius*1.1)}, @loops ],
);
# transform loops into ExtrusionPath objects

View File

@ -92,7 +92,7 @@ sub _plot {
foreach my $path (@paths) {
foreach my $line (@{$path->lines}) {
my @intersections = @{ Boost::Geometry::Utils::polygon_multi_linestring_intersection(
Slic3r::ExPolygon->new($line->grow(Slic3r::Geometry::scale $path->flow_spacing/2))->pp,
Slic3r::ExPolygon->new(@{$line->grow(Slic3r::Geometry::scale $path->flow_spacing/2)})->pp,
[ $self->line ],
) };
die "Intersection has more than two points!\n" if first { @$_ > 2 } @intersections;

View File

@ -35,16 +35,16 @@ use Slic3r::Geometry::Clipper qw(intersection_ex union_ex diff_ex);
is_deeply [ map $_->pp, @$intersection ], [[
[
[20, 12],
[20, 18],
[10, 18],
[10, 12],
[20, 12],
],
[
[14, 14],
[14, 16],
[16, 16],
[16, 14],
[14, 14],
],
]], 'hole is preserved after intersection';
}
@ -58,11 +58,11 @@ use Slic3r::Geometry::Clipper qw(intersection_ex union_ex diff_ex);
my $union = union_ex([ $contour1, $contour2, $hole ]);
is_deeply [ map $_->pp, @$union ], [[ [ [40,0], [40,40], [0,40], [0,0] ] ]],
is_deeply [ map $_->pp, @$union ], [[ [ [40,40], [0,40], [0,0], [40,0] ] ]],
'union of two ccw and one cw is a contour with no holes';
my $diff = diff_ex([ $contour1, $contour2 ], [ $hole ]);
is_deeply [ map $_->pp, @$diff ], [[ [ [40,0], [40,40], [0,40], [0,0] ], [ [15,15], [15,25], [25,25], [25,15] ] ]],
is_deeply [ map $_->pp, @$diff ], [[ [ [40,40], [0,40], [0,0], [40,0] ], [ [15,25], [25,25], [25,15], [15,15] ] ]],
'difference of a cw from two ccw is a contour with one hole';
}

View File

@ -68,7 +68,7 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
);
# check whether any part was left uncovered
my @grown_paths = map Slic3r::Polyline->new(@$_)->grow(scale $params->{flow_spacing}/2), @paths;
my @grown_paths = map @{Slic3r::Polyline->new(@$_)->grow(scale $params->{flow_spacing}/2)}, @paths;
my $uncovered = diff_ex([ @$expolygon ], [ @grown_paths ], 1);
# ignore very small dots

View File

@ -187,7 +187,7 @@ is Slic3r::Geometry::can_connect_points(@$points, $polygons), 0, 'can_connect_po
{
my $line = Slic3r::Line->new([10,10], [20,10]);
is +($line->grow(5))[0]->area, Slic3r::Polygon->new([5,5], [25,5], [25,15], [5,15])->area, 'grow line';
is $line->grow(5)->[0]->area, Slic3r::Polygon->new([10,5], [20,5], [20,15], [10,15])->area, 'grow line';
}
#==========================================================

View File

@ -67,7 +67,7 @@ ClipperPolygons_to_Slic3rExPolygons(const ClipperLib::Polygons &input, Slic3r::E
}
void
Slic3rPolygon_to_ClipperPolygon(const Slic3r::Polygon &input, ClipperLib::Polygon &output)
Slic3rPolygon_to_ClipperPolygon(const Slic3r::MultiPoint &input, ClipperLib::Polygon &output)
{
output.clear();
for (Slic3r::Points::const_iterator pit = input.points.begin(); pit != input.points.end(); ++pit) {
@ -75,11 +75,12 @@ Slic3rPolygon_to_ClipperPolygon(const Slic3r::Polygon &input, ClipperLib::Polygo
}
}
template <class T>
void
Slic3rPolygons_to_ClipperPolygons(const Slic3r::Polygons &input, ClipperLib::Polygons &output)
Slic3rPolygons_to_ClipperPolygons(const T &input, ClipperLib::Polygons &output)
{
output.clear();
for (Slic3r::Polygons::const_iterator it = input.begin(); it != input.end(); ++it) {
for (typename T::const_iterator it = input.begin(); it != input.end(); ++it) {
ClipperLib::Polygon p;
Slic3rPolygon_to_ClipperPolygon(*it, p);
output.push_back(p);
@ -129,6 +130,38 @@ offset(Slic3r::Polygons &polygons, Slic3r::Polygons &retval, const float delta,
delete output;
}
void
offset(Slic3r::Polylines &polylines, ClipperLib::Polygons &retval, const float delta,
double scale, ClipperLib::JoinType joinType, double miterLimit)
{
// read input
ClipperLib::Polygons* input = new ClipperLib::Polygons();
Slic3rPolygons_to_ClipperPolygons(polylines, *input);
// scale input
scaleClipperPolygons(*input, scale);
// perform offset
ClipperLib::OffsetPaths(*input, retval, (delta*scale), joinType, ClipperLib::etButt, miterLimit);
delete input;
// unscale output
scaleClipperPolygons(retval, 1/scale);
}
void
offset(Slic3r::Polylines &polylines, Slic3r::Polygons &retval, const float delta,
double scale, ClipperLib::JoinType joinType, double miterLimit)
{
// perform offset
ClipperLib::Polygons* output = new ClipperLib::Polygons();
offset(polylines, *output, delta, scale, joinType, miterLimit);
// convert into ExPolygons
ClipperPolygons_to_Slic3rPolygons(*output, retval);
delete output;
}
void
offset_ex(Slic3r::Polygons &polygons, Slic3r::ExPolygons &retval, const float delta,
double scale, ClipperLib::JoinType joinType, double miterLimit)

View File

@ -21,20 +21,31 @@ void AddOuterPolyNodeToExPolygons(ClipperLib::PolyNode& polynode, Slic3r::ExPoly
void PolyTreeToExPolygons(ClipperLib::PolyTree& polytree, Slic3r::ExPolygons& expolygons);
//-----------------------------------------------------------
void Slic3rPolygon_to_ClipperPolygon(const Slic3r::Polygon &input, ClipperLib::Polygon &output);
void Slic3rPolygons_to_ClipperPolygons(const Slic3r::Polygons &input, ClipperLib::Polygons &output);
void Slic3rPolygon_to_ClipperPolygon(const Slic3r::MultiPoint &input, ClipperLib::Polygon &output);
template <class T>
void Slic3rPolygons_to_ClipperPolygons(const T &input, ClipperLib::Polygons &output);
void ClipperPolygon_to_Slic3rPolygon(const ClipperLib::Polygon &input, Slic3r::Polygon &output);
void ClipperPolygons_to_Slic3rPolygons(const ClipperLib::Polygons &input, Slic3r::Polygons &output);
void ClipperPolygons_to_Slic3rExPolygons(const ClipperLib::Polygons &input, Slic3r::ExPolygons &output);
void scaleClipperPolygons(ClipperLib::Polygons &polygons, const double scale);
// offset Polygons
void offset(Slic3r::Polygons &polygons, ClipperLib::Polygons &retval, const float delta,
double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
double miterLimit = 3);
void offset(Slic3r::Polygons &polygons, Slic3r::Polygons &retval, const float delta,
double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
double miterLimit = 3);
// offset Polylines
void offset(Slic3r::Polylines &polylines, ClipperLib::Polygons &retval, const float delta,
double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtSquare,
double miterLimit = 3);
void offset(Slic3r::Polylines &polylines, Slic3r::Polygons &retval, const float delta,
double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtSquare,
double miterLimit = 3);
void offset_ex(Slic3r::Polygons &polygons, Slic3r::ExPolygons &retval, const float delta,
double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
double miterLimit = 3);

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
/*******************************************************************************
* *
* Author : Angus Johnson *
* Version : 5.1.5 *
* Date : 4 May 2013 *
* Version : 6.0.0 *
* Date : 30 October 2013 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2013 *
* *
@ -34,11 +34,30 @@
#ifndef clipper_hpp
#define clipper_hpp
#define CLIPPER_VERSION "6.0.0"
//use_int32: When enabled 32bit ints are used instead of 64bit ints. This
//improve performance but coordinate values are limited to the range +/- 46340
//#define use_int32
//use_xyz: adds a Z member to IntPoint. Adds a minor cost to perfomance.
//#define use_xyz
//use_lines: Enables line clipping. Adds a very minor cost to performance.
//#define use_lines
//When enabled, code developed with earlier versions of Clipper
//(ie prior to ver 6) should compile without changes.
//In a future update, this compatability code will be removed.
#define use_deprecated
#include <vector>
#include <set>
#include <stdexcept>
#include <cstring>
#include <cstdlib>
#include <ostream>
#include <functional>
namespace ClipperLib {
@ -50,23 +69,63 @@ enum PolyType { ptSubject, ptClip };
//see http://glprogramming.com/red/chapter11.html
enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative };
typedef signed long long long64;
typedef unsigned long long ulong64;
#ifdef use_int32
typedef int cInt;
typedef unsigned int cUInt;
#else
typedef signed long long cInt;
typedef unsigned long long cUInt;
#endif
struct IntPoint {
public:
long64 X;
long64 Y;
IntPoint(long64 x = 0, long64 y = 0): X(x), Y(y) {};
friend std::ostream& operator <<(std::ostream &s, IntPoint &p);
cInt X;
cInt Y;
#ifdef use_xyz
cInt Z;
IntPoint(cInt x = 0, cInt y = 0, cInt z = 0): X(x), Y(y), Z(z) {};
#else
IntPoint(cInt x = 0, cInt y = 0): X(x), Y(y) {};
#endif
friend inline bool operator== (const IntPoint& a, const IntPoint& b)
{
return a.X == b.X && a.Y == b.Y;
}
friend inline bool operator!= (const IntPoint& a, const IntPoint& b)
{
return a.X != b.X || a.Y != b.Y;
}
};
//------------------------------------------------------------------------------
typedef std::vector< IntPoint > Polygon;
typedef std::vector< Polygon > Polygons;
typedef std::vector< IntPoint > Path;
typedef std::vector< Path > Paths;
inline Path& operator <<(Path& poly, const IntPoint& p) {poly.push_back(p); return poly;}
inline Paths& operator <<(Paths& polys, const Path& p) {polys.push_back(p); return polys;}
std::ostream& operator <<(std::ostream &s, Polygon &p);
std::ostream& operator <<(std::ostream &s, Polygons &p);
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 Paths &p);
#ifdef use_deprecated
typedef signed long long long64; //backward compatibility only
typedef Path Polygon;
typedef Paths Polygons;
#endif
struct DoublePoint
{
double X;
double Y;
DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {}
DoublePoint(IntPoint ip) : X((double)ip.X), Y((double)ip.Y) {}
};
//------------------------------------------------------------------------------
#ifdef use_xyz
typedef void (*TZFillCallback)(IntPoint& z1, IntPoint& z2, IntPoint& pt);
#endif
class PolyNode;
typedef std::vector< PolyNode* > PolyNodes;
@ -75,13 +134,15 @@ class PolyNode
{
public:
PolyNode();
Polygon Contour;
Path Contour;
PolyNodes Childs;
PolyNode* Parent;
PolyNode* GetNext() const;
bool IsHole() const;
bool IsOpen() const;
int ChildCount() const;
private:
bool m_IsOpen;
PolyNode* GetNextSiblingUp() const;
unsigned Index; //node index in Parent.Childs
void AddChild(PolyNode& child);
@ -100,112 +161,62 @@ private:
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 Polygon &poly);
double Area(const Polygon &poly);
bool Orientation(const Path &poly);
double Area(const Path &poly);
#ifdef use_deprecated
void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys,
double delta, JoinType jointype = jtSquare, double limit = 0, bool autoFix = true);
void PolyTreeToPolygons(const PolyTree& polytree, Paths& paths);
void ReversePolygon(Path& p);
void ReversePolygons(Paths& p);
#endif
void SimplifyPolygon(const Polygon &in_poly, Polygons &out_polys, PolyFillType fillType = pftEvenOdd);
void SimplifyPolygons(const Polygons &in_polys, Polygons &out_polys, PolyFillType fillType = pftEvenOdd);
void SimplifyPolygons(Polygons &polys, PolyFillType fillType = pftEvenOdd);
void OffsetPaths(const Paths &in_polys, Paths &out_polys,
double delta, JoinType jointype, EndType endtype, double limit = 0);
void CleanPolygon(Polygon& in_poly, Polygon& out_poly, double distance = 1.415);
void CleanPolygons(Polygons& in_polys, Polygons& out_polys, double distance = 1.415);
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(Paths &polys, PolyFillType fillType = pftEvenOdd);
void PolyTreeToPolygons(PolyTree& polytree, Polygons& polygons);
void CleanPolygon(const Path& in_poly, Path& out_poly, double distance = 1.415);
void CleanPolygon(Path& poly, 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 ReversePolygon(Polygon& p);
void ReversePolygons(Polygons& p);
void MinkowkiSum(const Path& poly, const Path& path, Paths& solution, bool isClosed);
void MinkowkiDiff(const Path& poly, const Path& path, Paths& solution, bool isClosed);
//used internally ...
void PolyTreeToPaths(const PolyTree& polytree, Paths& paths);
void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths);
void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths);
void ReversePath(Path& p);
void ReversePaths(Paths& p);
struct IntRect { cInt left; cInt top; cInt right; cInt bottom; };
//enums that are used internally ...
enum EdgeSide { esLeft = 1, esRight = 2};
enum IntersectProtects { ipNone = 0, ipLeft = 1, ipRight = 2, ipBoth = 3 };
struct TEdge {
long64 xbot;
long64 ybot;
long64 xcurr;
long64 ycurr;
long64 xtop;
long64 ytop;
double dx;
long64 deltaX;
long64 deltaY;
PolyType polyType;
EdgeSide side;
int windDelta; //1 or -1 depending on winding direction
int windCnt;
int windCnt2; //winding count of the opposite polytype
int outIdx;
TEdge *next;
TEdge *prev;
TEdge *nextInLML;
TEdge *nextInAEL;
TEdge *prevInAEL;
TEdge *nextInSEL;
TEdge *prevInSEL;
};
struct IntersectNode {
TEdge *edge1;
TEdge *edge2;
IntPoint pt;
IntersectNode *next;
};
struct LocalMinima {
long64 Y;
TEdge *leftBound;
TEdge *rightBound;
LocalMinima *next;
};
struct Scanbeam {
long64 Y;
Scanbeam *next;
};
struct OutPt; //forward declaration
struct OutRec {
int idx;
bool isHole;
OutRec *FirstLeft; //see comments in clipper.pas
PolyNode *polyNode;
OutPt *pts;
OutPt *bottomPt;
};
struct OutPt {
int idx;
IntPoint pt;
OutPt *next;
OutPt *prev;
};
struct JoinRec {
IntPoint pt1a;
IntPoint pt1b;
int poly1Idx;
IntPoint pt2a;
IntPoint pt2b;
int poly2Idx;
};
struct HorzJoinRec {
TEdge *edge;
int savedIdx;
};
struct IntRect { long64 left; long64 top; long64 right; long64 bottom; };
//forward declarations (for stuff used internally) ...
struct TEdge;
struct IntersectNode;
struct LocalMinima;
struct Scanbeam;
struct OutPt;
struct OutRec;
struct Join;
typedef std::vector < OutRec* > PolyOutList;
typedef std::vector < TEdge* > EdgeList;
typedef std::vector < JoinRec* > JoinList;
typedef std::vector < HorzJoinRec* > HorzJoinList;
typedef std::vector < Join* > JoinList;
//------------------------------------------------------------------------------
//ClipperBase is the ancestor to the Clipper class. It should not be
//instantiated directly. This class simply abstracts the conversion of sets of
@ -215,29 +226,43 @@ class ClipperBase
public:
ClipperBase();
virtual ~ClipperBase();
bool AddPolygon(const Polygon &pg, PolyType polyType);
bool AddPolygons( const Polygons &ppg, PolyType polyType);
bool AddPath(const Path &pg, 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();
IntRect GetBounds();
bool PreserveCollinear() {return m_PreserveCollinear;};
void PreserveCollinear(bool value) {m_PreserveCollinear = value;};
protected:
void DisposeLocalMinimaList();
TEdge* AddBoundsToLML(TEdge *e);
TEdge* AddBoundsToLML(TEdge *e, bool IsClosed);
void PopLocalMinima();
virtual void Reset();
void InsertLocalMinima(LocalMinima *newLm);
void DoMinimaLML(TEdge* E1, TEdge* E2, bool IsClosed);
TEdge* DescendToMin(TEdge *&E);
void AscendToMax(TEdge *&E, bool Appending, bool IsClosed);
LocalMinima *m_CurrentLM;
LocalMinima *m_MinimaList;
bool m_UseFullRange;
EdgeList m_edges;
bool m_PreserveCollinear;
bool m_HasOpenPaths;
};
//------------------------------------------------------------------------------
class Clipper : public virtual ClipperBase
{
public:
Clipper();
Clipper(int initOptions = 0);
~Clipper();
bool Execute(ClipType clipType,
Polygons &solution,
Paths &solution,
PolyFillType subjFillType = pftEvenOdd,
PolyFillType clipFillType = pftEvenOdd);
bool Execute(ClipType clipType,
@ -247,17 +272,21 @@ public:
void Clear();
bool ReverseSolution() {return m_ReverseOutput;};
void ReverseSolution(bool value) {m_ReverseOutput = value;};
bool ForceSimple() {return m_ForceSimple;};
void ForceSimple(bool value) {m_ForceSimple = value;};
bool StrictlySimple() {return m_StrictSimple;};
void StrictlySimple(bool value) {m_StrictSimple = value;};
//set the callback function for z value filling on intersections (otherwise Z is 0)
#ifdef use_xyz
void ZFillFunction(TZFillCallback zFillFunc);
#endif
protected:
void Reset();
virtual bool ExecuteInternal();
private:
PolyOutList m_PolyOuts;
JoinList m_Joins;
HorzJoinList m_HorizJoins;
JoinList m_GhostJoins;
ClipType m_ClipType;
Scanbeam *m_Scanbeam;
std::set< cInt, std::greater<cInt> > m_Scanbeam;
TEdge *m_ActiveEdges;
TEdge *m_SortedEdges;
IntersectNode *m_IntersectNodes;
@ -266,15 +295,17 @@ private:
PolyFillType m_SubjFillType;
bool m_ReverseOutput;
bool m_UsingPolyTree;
bool m_ForceSimple;
void DisposeScanbeamList();
bool m_StrictSimple;
#ifdef use_xyz
TZFillCallback m_ZFill; //custom callback
#endif
void SetWindingCount(TEdge& edge);
bool IsEvenOddFillType(const TEdge& edge) const;
bool IsEvenOddAltFillType(const TEdge& edge) const;
void InsertScanbeam(const long64 Y);
long64 PopScanbeam();
void InsertLocalMinimaIntoAEL(const long64 botY);
void InsertEdgeIntoAEL(TEdge *edge);
void InsertScanbeam(const cInt Y);
cInt PopScanbeam();
void InsertLocalMinimaIntoAEL(const cInt botY);
void InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge);
void AddEdgeToSEL(TEdge *edge);
void CopyAELToSEL();
void DeleteFromSEL(TEdge *e);
@ -282,27 +313,28 @@ private:
void UpdateEdgeIntoAEL(TEdge *&e);
void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2);
bool IsContributing(const TEdge& edge) const;
bool IsTopHorz(const long64 XPos);
bool IsTopHorz(const cInt XPos);
void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2);
void DoMaxima(TEdge *e, long64 topY);
void ProcessHorizontals();
void ProcessHorizontal(TEdge *horzEdge);
void DoMaxima(TEdge *e);
void PrepareHorzJoins(TEdge* horzEdge, bool isTopOfScanbeam);
void ProcessHorizontals(bool IsTopOfScanbeam);
void ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam);
void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
void AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
OutPt* AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
OutRec* GetOutRec(int idx);
void AppendPolygon(TEdge *e1, TEdge *e2);
void IntersectEdges(TEdge *e1, TEdge *e2,
const IntPoint &pt, const IntersectProtects protects);
const IntPoint &pt, bool protect = false);
OutRec* CreateOutRec();
void AddOutPt(TEdge *e, const IntPoint &pt);
void DisposeAllPolyPts();
OutPt* AddOutPt(TEdge *e, const IntPoint &pt);
void DisposeAllOutRecs();
void DisposeOutRec(PolyOutList::size_type index);
bool ProcessIntersections(const long64 botY, const long64 topY);
void AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt);
void BuildIntersectList(const long64 botY, const long64 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 ProcessIntersectList();
void ProcessEdgesAtTopOfScanbeam(const long64 topY);
void BuildResult(Polygons& polys);
void ProcessEdgesAtTopOfScanbeam(const cInt topY);
void BuildResult(Paths& polys);
void BuildResult2(PolyTree& polytree);
void SetHoleState(TEdge *e, OutRec *outrec);
void DisposeIntersectNodes();
@ -310,19 +342,19 @@ private:
void FixupOutPolygon(OutRec &outrec);
bool IsHole(TEdge *e);
void FixHoleLinkage(OutRec &outrec);
void AddJoin(TEdge *e1, TEdge *e2, int e1OutIdx = -1, int e2OutIdx = -1);
void AddJoin(OutPt *op1, OutPt *op2, const IntPoint offPt);
void ClearJoins();
void AddHorzJoin(TEdge *e, int idx);
void ClearHorzJoins();
bool JoinPoints(const JoinRec *j, OutPt *&p1, OutPt *&p2);
void FixupJoinRecs(JoinRec *j, OutPt *pt, unsigned startIdx);
void ClearGhostJoins();
void AddGhostJoin(OutPt *op, const IntPoint offPt);
bool JoinPoints(const Join *j, OutPt *&p1, OutPt *&p2);
void JoinCommonEdges();
void DoSimplePolygons();
void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec);
void FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec);
#ifdef use_xyz
void SetZ(IntPoint& pt, TEdge& e);
#endif
};
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
class clipperException : public std::exception

View File

@ -23,59 +23,59 @@ my $expolygon = Slic3r::ExPolygon->new($square, $hole_in_square);
{
my $result = Slic3r::Geometry::Clipper::offset([ $square, $hole_in_square ], 5);
is_deeply [ map $_->pp, @$result ], [ [
[205, 95],
[205, 205],
[95, 205],
[95, 95],
[205, 95],
], [
[155, 145],
[145, 145],
[145, 155],
[155, 155],
[155, 145],
] ], 'offset';
}
{
my $result = Slic3r::Geometry::Clipper::offset_ex([ @$expolygon ], 5);
is_deeply $result->[0]->pp, [ [
[205, 95],
[205, 205],
[95, 205],
[95, 95],
[205, 95],
], [
[145, 145],
[145, 155],
[155, 155],
[155, 145],
[145, 145],
] ], 'offset_ex';
}
{
my $result = Slic3r::Geometry::Clipper::offset2_ex([ @$expolygon ], 5, -2);
is_deeply $result->[0]->pp, [ [
[203, 97],
[203, 203],
[97, 203],
[97, 97],
[203, 97],
], [
[143, 143],
[143, 157],
[157, 157],
[157, 143],
[143, 143],
] ], 'offset2_ex';
}
{
my $expolygon2 = Slic3r::ExPolygon->new([
[20000000, 0],
[20000000, 20000000],
[0, 20000000],
[0, 0],
[20000000, 0],
], [
[5000000, 5000000],
[5000000, 15000000],
[15000000, 15000000],
[15000000, 5000000],
[5000000, 5000000],
]);
my $result = Slic3r::Geometry::Clipper::offset2_ex([ @$expolygon2 ], -1, +1);
is_deeply $result->[0]->pp, $expolygon2->pp, 'offset2_ex';
@ -85,7 +85,7 @@ my $expolygon = Slic3r::ExPolygon->new($square, $hole_in_square);
my $polygon1 = Slic3r::Polygon->new(@$square);
my $polygon2 = Slic3r::Polygon->new(reverse @$hole_in_square);
my $result = Slic3r::Geometry::Clipper::diff_ex([$polygon1], [$polygon2]);
is_deeply $result->[0]->pp, $expolygon->pp, 'diff_ex';
is $result->[0]->area, $expolygon->area, 'diff_ex';
}
__END__

View File

@ -2,6 +2,7 @@
%{
#include <myinit.h>
#include "ClipperUtils.hpp"
#include "Polyline.hpp"
%}
@ -68,5 +69,18 @@ Polyline::rotate(angle, center_sv)
center.from_SV_check(center_sv);
THIS->rotate(angle, &center);
Polygons
Polyline::grow(delta, scale = CLIPPER_OFFSET_SCALE, joinType = ClipperLib::jtSquare, miterLimit = 3)
const float delta
double scale
ClipperLib::JoinType joinType
double miterLimit
CODE:
Polylines polylines;
polylines.push_back(*THIS);
offset(polylines, RETVAL, delta, scale, joinType, miterLimit);
OUTPUT:
RETVAL
%}
};