ruby_clipper 5.0.3 → 6.2.1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
-