ruby_clipper 5.0.3 → 6.2.1.5.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,10 +1,10 @@
1
1
  /*******************************************************************************
2
2
  * *
3
3
  * Author : Angus Johnson *
4
- * Version : 5.0.1 *
5
- * Date : 30 December 2012 *
4
+ * Version : 6.2.1 *
5
+ * Date : 31 October 2014 *
6
6
  * Website : http://www.angusj.com *
7
- * Copyright : Angus Johnson 2010-2012 *
7
+ * Copyright : Angus Johnson 2010-2014 *
8
8
  * *
9
9
  * License: *
10
10
  * Use, modification & distribution is subject to Boost Software License Ver 1. *
@@ -26,7 +26,7 @@
26
26
  * Paper no. DETC2005-85513 pp. 565-575 *
27
27
  * ASME 2005 International Design Engineering Technical Conferences *
28
28
  * and Computers and Information in Engineering Conference (IDETC/CIE2005) *
29
- * September 2428, 2005 , Long Beach, California, USA *
29
+ * September 24-28, 2005 , Long Beach, California, USA *
30
30
  * http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf *
31
31
  * *
32
32
  *******************************************************************************/
@@ -34,11 +34,29 @@
34
34
  #ifndef clipper_hpp
35
35
  #define clipper_hpp
36
36
 
37
+ #define CLIPPER_VERSION "6.2.0"
38
+
39
+ //use_int32: When enabled 32bit ints are used instead of 64bit ints. This
40
+ //improve performance but coordinate values are limited to the range +/- 46340
41
+ //#define use_int32
42
+
43
+ //use_xyz: adds a Z member to IntPoint. Adds a minor cost to perfomance.
44
+ //#define use_xyz
45
+
46
+ //use_lines: Enables line clipping. Adds a very minor cost to performance.
47
+ //#define use_lines
48
+
49
+ //use_deprecated: Enables temporary support for the obsolete functions
50
+ //#define use_deprecated
51
+
37
52
  #include <vector>
53
+ #include <set>
38
54
  #include <stdexcept>
39
55
  #include <cstring>
40
56
  #include <cstdlib>
41
57
  #include <ostream>
58
+ #include <functional>
59
+ #include <queue>
42
60
 
43
61
  namespace ClipperLib {
44
62
 
@@ -50,129 +68,149 @@ enum PolyType { ptSubject, ptClip };
50
68
  //see http://glprogramming.com/red/chapter11.html
51
69
  enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative };
52
70
 
53
- typedef signed long long long64;
54
- typedef unsigned long long ulong64;
71
+ #ifdef use_int32
72
+ typedef int cInt;
73
+ static cInt const loRange = 0x7FFF;
74
+ static cInt const hiRange = 0x7FFF;
75
+ #else
76
+ typedef signed long long cInt;
77
+ static cInt const loRange = 0x3FFFFFFF;
78
+ static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL;
79
+ typedef signed long long long64; //used by Int128 class
80
+ typedef unsigned long long ulong64;
81
+
82
+ #endif
55
83
 
56
84
  struct IntPoint {
57
- public:
58
- long64 X;
59
- long64 Y;
60
- IntPoint(long64 x = 0, long64 y = 0): X(x), Y(y) {};
61
- friend std::ostream& operator <<(std::ostream &s, IntPoint &p);
85
+ cInt X;
86
+ cInt Y;
87
+ #ifdef use_xyz
88
+ cInt Z;
89
+ IntPoint(cInt x = 0, cInt y = 0, cInt z = 0): X(x), Y(y), Z(z) {};
90
+ #else
91
+ IntPoint(cInt x = 0, cInt y = 0): X(x), Y(y) {};
92
+ #endif
93
+
94
+ friend inline bool operator== (const IntPoint& a, const IntPoint& b)
95
+ {
96
+ return a.X == b.X && a.Y == b.Y;
97
+ }
98
+ friend inline bool operator!= (const IntPoint& a, const IntPoint& b)
99
+ {
100
+ return a.X != b.X || a.Y != b.Y;
101
+ }
62
102
  };
103
+ //------------------------------------------------------------------------------
104
+
105
+ typedef std::vector< IntPoint > Path;
106
+ typedef std::vector< Path > Paths;
63
107
 
64
- typedef std::vector< IntPoint > Polygon;
65
- typedef std::vector< Polygon > Polygons;
108
+ inline Path& operator <<(Path& poly, const IntPoint& p) {poly.push_back(p); return poly;}
109
+ inline Paths& operator <<(Paths& polys, const Path& p) {polys.push_back(p); return polys;}
66
110
 
67
- std::ostream& operator <<(std::ostream &s, Polygon &p);
68
- std::ostream& operator <<(std::ostream &s, Polygons &p);
111
+ std::ostream& operator <<(std::ostream &s, const IntPoint &p);
112
+ std::ostream& operator <<(std::ostream &s, const Path &p);
113
+ std::ostream& operator <<(std::ostream &s, const Paths &p);
69
114
 
70
- struct ExPolygon {
71
- Polygon outer;
72
- Polygons holes;
115
+ struct DoublePoint
116
+ {
117
+ double X;
118
+ double Y;
119
+ DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {}
120
+ DoublePoint(IntPoint ip) : X((double)ip.X), Y((double)ip.Y) {}
73
121
  };
74
- typedef std::vector< ExPolygon > ExPolygons;
122
+ //------------------------------------------------------------------------------
75
123
 
76
- enum JoinType { jtSquare, jtRound, jtMiter };
124
+ #ifdef use_xyz
125
+ typedef void (*ZFillCallback)(IntPoint& e1bot, IntPoint& e1top, IntPoint& e2bot, IntPoint& e2top, IntPoint& pt);
126
+ #endif
77
127
 
78
- bool Orientation(const Polygon &poly);
79
- double Area(const Polygon &poly);
80
- void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys,
81
- double delta, JoinType jointype = jtSquare, double MiterLimit = 2, bool AutoFix = true);
82
- void SimplifyPolygon(const Polygon &in_poly, Polygons &out_polys, PolyFillType fillType = pftEvenOdd);
83
- void SimplifyPolygons(const Polygons &in_polys, Polygons &out_polys, PolyFillType fillType = pftEvenOdd);
84
- void SimplifyPolygons(Polygons &polys, PolyFillType fillType = pftEvenOdd);
128
+ enum InitOptions {ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4};
129
+ enum JoinType {jtSquare, jtRound, jtMiter};
130
+ enum EndType {etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound};
85
131
 
86
- void ReversePolygon(Polygon& p);
87
- void ReversePolygons(Polygons& p);
132
+ class PolyNode;
133
+ typedef std::vector< PolyNode* > PolyNodes;
88
134
 
89
- //used internally ...
90
- enum EdgeSide { esLeft = 1, esRight = 2};
91
- enum IntersectProtects { ipNone = 0, ipLeft = 1, ipRight = 2, ipBoth = 3 };
92
-
93
- struct TEdge {
94
- long64 xbot;
95
- long64 ybot;
96
- long64 xcurr;
97
- long64 ycurr;
98
- long64 xtop;
99
- long64 ytop;
100
- double dx;
101
- long64 deltaX;
102
- long64 deltaY;
103
- long64 tmpX;
104
- PolyType polyType;
105
- EdgeSide side;
106
- int windDelta; //1 or -1 depending on winding direction
107
- int windCnt;
108
- int windCnt2; //winding count of the opposite polytype
109
- int outIdx;
110
- TEdge *next;
111
- TEdge *prev;
112
- TEdge *nextInLML;
113
- TEdge *nextInAEL;
114
- TEdge *prevInAEL;
115
- TEdge *nextInSEL;
116
- TEdge *prevInSEL;
135
+ class PolyNode
136
+ {
137
+ public:
138
+ PolyNode();
139
+ virtual ~PolyNode(){};
140
+ Path Contour;
141
+ PolyNodes Childs;
142
+ PolyNode* Parent;
143
+ PolyNode* GetNext() const;
144
+ bool IsHole() const;
145
+ bool IsOpen() const;
146
+ int ChildCount() const;
147
+ private:
148
+ unsigned Index; //node index in Parent.Childs
149
+ bool m_IsOpen;
150
+ JoinType m_jointype;
151
+ EndType m_endtype;
152
+ PolyNode* GetNextSiblingUp() const;
153
+ void AddChild(PolyNode& child);
154
+ friend class Clipper; //to access Index
155
+ friend class ClipperOffset;
117
156
  };
118
157
 
119
- struct IntersectNode {
120
- TEdge *edge1;
121
- TEdge *edge2;
122
- IntPoint pt;
123
- IntersectNode *next;
158
+ class PolyTree: public PolyNode
159
+ {
160
+ public:
161
+ ~PolyTree(){Clear();};
162
+ PolyNode* GetFirst() const;
163
+ void Clear();
164
+ int Total() const;
165
+ private:
166
+ PolyNodes AllNodes;
167
+ friend class Clipper; //to access AllNodes
124
168
  };
125
169
 
126
- struct LocalMinima {
127
- long64 Y;
128
- TEdge *leftBound;
129
- TEdge *rightBound;
130
- LocalMinima *next;
131
- };
170
+ bool Orientation(const Path &poly);
171
+ double Area(const Path &poly);
172
+ int PointInPolygon(const IntPoint &pt, const Path &path);
132
173
 
133
- struct Scanbeam {
134
- long64 Y;
135
- Scanbeam *next;
136
- };
174
+ void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
175
+ void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
176
+ void SimplifyPolygons(Paths &polys, PolyFillType fillType = pftEvenOdd);
137
177
 
138
- struct OutPt; //forward declaration
178
+ void CleanPolygon(const Path& in_poly, Path& out_poly, double distance = 1.415);
179
+ void CleanPolygon(Path& poly, double distance = 1.415);
180
+ void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance = 1.415);
181
+ void CleanPolygons(Paths& polys, double distance = 1.415);
139
182
 
140
- struct OutRec {
141
- int idx;
142
- bool isHole;
143
- OutRec *FirstLeft;
144
- OutRec *AppendLink;
145
- OutPt *pts;
146
- OutPt *bottomPt;
147
- };
183
+ void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed);
184
+ void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution, bool pathIsClosed);
185
+ void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution);
148
186
 
149
- struct OutPt {
150
- int idx;
151
- IntPoint pt;
152
- OutPt *next;
153
- OutPt *prev;
154
- };
187
+ void PolyTreeToPaths(const PolyTree& polytree, Paths& paths);
188
+ void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths);
189
+ void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths);
155
190
 
156
- struct JoinRec {
157
- IntPoint pt1a;
158
- IntPoint pt1b;
159
- int poly1Idx;
160
- IntPoint pt2a;
161
- IntPoint pt2b;
162
- int poly2Idx;
163
- };
191
+ void ReversePath(Path& p);
192
+ void ReversePaths(Paths& p);
164
193
 
165
- struct HorzJoinRec {
166
- TEdge *edge;
167
- int savedIdx;
168
- };
194
+ struct IntRect { cInt left; cInt top; cInt right; cInt bottom; };
195
+
196
+ //enums that are used internally ...
197
+ enum EdgeSide { esLeft = 1, esRight = 2};
169
198
 
170
- struct IntRect { long64 left; long64 top; long64 right; long64 bottom; };
199
+ //forward declarations (for stuff used internally) ...
200
+ struct TEdge;
201
+ struct IntersectNode;
202
+ struct LocalMinimum;
203
+ struct Scanbeam;
204
+ struct OutPt;
205
+ struct OutRec;
206
+ struct Join;
171
207
 
172
208
  typedef std::vector < OutRec* > PolyOutList;
173
209
  typedef std::vector < TEdge* > EdgeList;
174
- typedef std::vector < JoinRec* > JoinList;
175
- typedef std::vector < HorzJoinRec* > HorzJoinList;
210
+ typedef std::vector < Join* > JoinList;
211
+ typedef std::vector < IntersectNode* > IntersectList;
212
+
213
+ //------------------------------------------------------------------------------
176
214
 
177
215
  //ClipperBase is the ancestor to the Clipper class. It should not be
178
216
  //instantiated directly. This class simply abstracts the conversion of sets of
@@ -182,63 +220,83 @@ class ClipperBase
182
220
  public:
183
221
  ClipperBase();
184
222
  virtual ~ClipperBase();
185
- bool AddPolygon(const Polygon &pg, PolyType polyType);
186
- bool AddPolygons( const Polygons &ppg, PolyType polyType);
223
+ bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed);
224
+ bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed);
187
225
  virtual void Clear();
188
226
  IntRect GetBounds();
227
+ bool PreserveCollinear() {return m_PreserveCollinear;};
228
+ void PreserveCollinear(bool value) {m_PreserveCollinear = value;};
189
229
  protected:
190
230
  void DisposeLocalMinimaList();
191
- TEdge* AddBoundsToLML(TEdge *e);
231
+ TEdge* AddBoundsToLML(TEdge *e, bool IsClosed);
192
232
  void PopLocalMinima();
193
233
  virtual void Reset();
194
- void InsertLocalMinima(LocalMinima *newLm);
195
- LocalMinima *m_CurrentLM;
196
- LocalMinima *m_MinimaList;
234
+ TEdge* ProcessBound(TEdge* E, bool IsClockwise);
235
+ void DoMinimaLML(TEdge* E1, TEdge* E2, bool IsClosed);
236
+ TEdge* DescendToMin(TEdge *&E);
237
+ void AscendToMax(TEdge *&E, bool Appending, bool IsClosed);
238
+
239
+ typedef std::vector<LocalMinimum> MinimaList;
240
+ MinimaList::iterator m_CurrentLM;
241
+ MinimaList m_MinimaList;
242
+
197
243
  bool m_UseFullRange;
198
244
  EdgeList m_edges;
245
+ bool m_PreserveCollinear;
246
+ bool m_HasOpenPaths;
199
247
  };
248
+ //------------------------------------------------------------------------------
200
249
 
201
250
  class Clipper : public virtual ClipperBase
202
251
  {
203
252
  public:
204
- Clipper();
253
+ Clipper(int initOptions = 0);
205
254
  ~Clipper();
206
255
  bool Execute(ClipType clipType,
207
- Polygons &solution,
208
- PolyFillType subjFillType = pftEvenOdd,
209
- PolyFillType clipFillType = pftEvenOdd);
256
+ Paths &solution,
257
+ PolyFillType subjFillType = pftEvenOdd,
258
+ PolyFillType clipFillType = pftEvenOdd);
210
259
  bool Execute(ClipType clipType,
211
- ExPolygons &solution,
212
- PolyFillType subjFillType = pftEvenOdd,
213
- PolyFillType clipFillType = pftEvenOdd);
214
- void Clear();
260
+ PolyTree &polytree,
261
+ PolyFillType subjFillType = pftEvenOdd,
262
+ PolyFillType clipFillType = pftEvenOdd);
215
263
  bool ReverseSolution() {return m_ReverseOutput;};
216
264
  void ReverseSolution(bool value) {m_ReverseOutput = value;};
265
+ bool StrictlySimple() {return m_StrictSimple;};
266
+ void StrictlySimple(bool value) {m_StrictSimple = value;};
267
+ //set the callback function for z value filling on intersections (otherwise Z is 0)
268
+ #ifdef use_xyz
269
+ void ZFillFunction(ZFillCallback zFillFunc);
270
+ #endif
217
271
  protected:
218
272
  void Reset();
219
273
  virtual bool ExecuteInternal();
220
274
  private:
221
275
  PolyOutList m_PolyOuts;
222
276
  JoinList m_Joins;
223
- HorzJoinList m_HorizJoins;
277
+ JoinList m_GhostJoins;
278
+ IntersectList m_IntersectList;
224
279
  ClipType m_ClipType;
225
- Scanbeam *m_Scanbeam;
280
+ typedef std::priority_queue<cInt> ScanbeamList;
281
+ ScanbeamList m_Scanbeam;
226
282
  TEdge *m_ActiveEdges;
227
283
  TEdge *m_SortedEdges;
228
- IntersectNode *m_IntersectNodes;
229
- bool m_ExecuteLocked;
230
- PolyFillType m_ClipFillType;
231
- PolyFillType m_SubjFillType;
232
- bool m_ReverseOutput;
233
- bool m_UsingExPolygons;
234
- void DisposeScanbeamList();
284
+ bool m_ExecuteLocked;
285
+ PolyFillType m_ClipFillType;
286
+ PolyFillType m_SubjFillType;
287
+ bool m_ReverseOutput;
288
+ bool m_UsingPolyTree;
289
+ bool m_StrictSimple;
290
+ #ifdef use_xyz
291
+ ZFillCallback m_ZFill; //custom callback
292
+ #endif
235
293
  void SetWindingCount(TEdge& edge);
236
294
  bool IsEvenOddFillType(const TEdge& edge) const;
237
295
  bool IsEvenOddAltFillType(const TEdge& edge) const;
238
- void InsertScanbeam(const long64 Y);
239
- long64 PopScanbeam();
240
- void InsertLocalMinimaIntoAEL(const long64 botY);
241
- void InsertEdgeIntoAEL(TEdge *edge);
296
+ void InsertScanbeam(const cInt Y);
297
+ cInt PopScanbeam();
298
+ void InsertLocalMinimaIntoAEL(const cInt botY);
299
+ void InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge);
242
300
  void AddEdgeToSEL(TEdge *edge);
243
301
  void CopyAELToSEL();
244
302
  void DeleteFromSEL(TEdge *e);
@@ -246,46 +304,77 @@ private:
246
304
  void UpdateEdgeIntoAEL(TEdge *&e);
247
305
  void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2);
248
306
  bool IsContributing(const TEdge& edge) const;
249
- bool IsTopHorz(const long64 XPos);
307
+ bool IsTopHorz(const cInt XPos);
250
308
  void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2);
251
- void DoMaxima(TEdge *e, long64 topY);
252
- void ProcessHorizontals();
253
- void ProcessHorizontal(TEdge *horzEdge);
309
+ void DoMaxima(TEdge *e);
310
+ void ProcessHorizontals(bool IsTopOfScanbeam);
311
+ void ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam);
254
312
  void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
255
- void AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
313
+ OutPt* AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
314
+ OutRec* GetOutRec(int idx);
256
315
  void AppendPolygon(TEdge *e1, TEdge *e2);
257
- void DoEdge1(TEdge *edge1, TEdge *edge2, const IntPoint &pt);
258
- void DoEdge2(TEdge *edge1, TEdge *edge2, const IntPoint &pt);
259
- void DoBothEdges(TEdge *edge1, TEdge *edge2, const IntPoint &pt);
260
- void IntersectEdges(TEdge *e1, TEdge *e2,
261
- const IntPoint &pt, const IntersectProtects protects);
316
+ void IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &pt);
262
317
  OutRec* CreateOutRec();
263
- void AddOutPt(TEdge *e, const IntPoint &pt);
264
- void DisposeAllPolyPts();
318
+ OutPt* AddOutPt(TEdge *e, const IntPoint &pt);
319
+ void DisposeAllOutRecs();
265
320
  void DisposeOutRec(PolyOutList::size_type index);
266
- bool ProcessIntersections(const long64 botY, const long64 topY);
267
- void AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt);
268
- void BuildIntersectList(const long64 botY, const long64 topY);
321
+ bool ProcessIntersections(const cInt topY);
322
+ void BuildIntersectList(const cInt topY);
269
323
  void ProcessIntersectList();
270
- void ProcessEdgesAtTopOfScanbeam(const long64 topY);
271
- void BuildResult(Polygons& polys);
272
- void BuildResultEx(ExPolygons& polys);
273
- void SetHoleState(TEdge *e, OutRec *OutRec);
324
+ void ProcessEdgesAtTopOfScanbeam(const cInt topY);
325
+ void BuildResult(Paths& polys);
326
+ void BuildResult2(PolyTree& polytree);
327
+ void SetHoleState(TEdge *e, OutRec *outrec);
274
328
  void DisposeIntersectNodes();
275
- bool FixupIntersections();
276
- void FixupOutPolygon(OutRec &outRec);
329
+ bool FixupIntersectionOrder();
330
+ void FixupOutPolygon(OutRec &outrec);
277
331
  bool IsHole(TEdge *e);
278
- void FixHoleLinkage(OutRec *outRec);
279
- void AddJoin(TEdge *e1, TEdge *e2, int e1OutIdx = -1, int e2OutIdx = -1);
332
+ bool FindOwnerFromSplitRecs(OutRec &outRec, OutRec *&currOrfl);
333
+ void FixHoleLinkage(OutRec &outrec);
334
+ void AddJoin(OutPt *op1, OutPt *op2, const IntPoint offPt);
280
335
  void ClearJoins();
281
- void AddHorzJoin(TEdge *e, int idx);
282
- void ClearHorzJoins();
283
- bool JoinPoints(const JoinRec *j, OutPt *&p1, OutPt *&p2);
284
- void FixupJoinRecs(JoinRec *j, OutPt *pt, unsigned startIdx);
336
+ void ClearGhostJoins();
337
+ void AddGhostJoin(OutPt *op, const IntPoint offPt);
338
+ bool JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2);
285
339
  void JoinCommonEdges();
340
+ void DoSimplePolygons();
341
+ void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec);
342
+ void FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec);
343
+ #ifdef use_xyz
344
+ void SetZ(IntPoint& pt, TEdge& e1, TEdge& e2);
345
+ #endif
286
346
  };
287
-
288
347
  //------------------------------------------------------------------------------
348
+
349
+ class ClipperOffset
350
+ {
351
+ public:
352
+ ClipperOffset(double miterLimit = 2.0, double roundPrecision = 0.25);
353
+ ~ClipperOffset();
354
+ void AddPath(const Path& path, JoinType joinType, EndType endType);
355
+ void AddPaths(const Paths& paths, JoinType joinType, EndType endType);
356
+ void Execute(Paths& solution, double delta);
357
+ void Execute(PolyTree& solution, double delta);
358
+ void Clear();
359
+ double MiterLimit;
360
+ double ArcTolerance;
361
+ private:
362
+ Paths m_destPolys;
363
+ Path m_srcPoly;
364
+ Path m_destPoly;
365
+ std::vector<DoublePoint> m_normals;
366
+ double m_delta, m_sinA, m_sin, m_cos;
367
+ double m_miterLim, m_StepsPerRad;
368
+ IntPoint m_lowest;
369
+ PolyNode m_polyNodes;
370
+
371
+ void FixOrientations();
372
+ void DoOffset(double delta);
373
+ void OffsetPoint(int j, int& k, JoinType jointype);
374
+ void DoSquare(int j, int k);
375
+ void DoMiter(int j, int k, double r);
376
+ void DoRound(int j, int k);
377
+ };
289
378
  //------------------------------------------------------------------------------
290
379
 
291
380
  class clipperException : public std::exception
@@ -302,5 +391,3 @@ class clipperException : public std::exception
302
391
  } //ClipperLib namespace
303
392
 
304
393
  #endif //clipper_hpp
305
-
306
-