clipper.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. /*******************************************************************************
  2. * *
  3. * Author : Angus Johnson *
  4. * Version : 6.1.3a *
  5. * Date : 22 January 2014 *
  6. * Website : http://www.angusj.com *
  7. * Copyright : Angus Johnson 2010-2014 *
  8. * *
  9. * License: *
  10. * Use, modification & distribution is subject to Boost Software License Ver 1. *
  11. * http://www.boost.org/LICENSE_1_0.txt *
  12. * *
  13. * Attributions: *
  14. * The code in this library is an extension of Bala Vatti's clipping algorithm: *
  15. * "A generic solution to polygon clipping" *
  16. * Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. *
  17. * http://portal.acm.org/citation.cfm?id=129906 *
  18. * *
  19. * Computer graphics and geometric modeling: implementation and algorithms *
  20. * By Max K. Agoston *
  21. * Springer; 1 edition (January 4, 2005) *
  22. * http://books.google.com/books?q=vatti+clipping+agoston *
  23. * *
  24. * See also: *
  25. * "Polygon Offsetting by Computing Winding Numbers" *
  26. * Paper no. DETC2005-85513 pp. 565-575 *
  27. * ASME 2005 International Design Engineering Technical Conferences *
  28. * and Computers and Information in Engineering Conference (IDETC/CIE2005) *
  29. * September 24-28, 2005 , Long Beach, California, USA *
  30. * http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf *
  31. * *
  32. *******************************************************************************/
  33. #ifndef clipper_hpp
  34. #define clipper_hpp
  35. #define CLIPPER_VERSION "6.1.3"
  36. //use_int32: When enabled 32bit ints are used instead of 64bit ints. This
  37. //improve performance but coordinate values are limited to the range +/- 46340
  38. //#define use_int32
  39. //use_xyz: adds a Z member to IntPoint. Adds a minor cost to perfomance.
  40. //#define use_xyz
  41. //use_lines: Enables line clipping. Adds a very minor cost to performance.
  42. //#define use_lines
  43. //use_deprecated: Enables support for the obsolete OffsetPaths() function
  44. //which has been replace with the ClipperOffset class.
  45. #define use_deprecated
  46. #include <vector>
  47. #include <set>
  48. #include <stdexcept>
  49. #include <cstring>
  50. #include <cstdlib>
  51. #include <ostream>
  52. #include <functional>
  53. namespace ClipperLib {
  54. enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor };
  55. enum PolyType { ptSubject, ptClip };
  56. //By far the most widely used winding rules for polygon filling are
  57. //EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32)
  58. //Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL)
  59. //see http://glprogramming.com/red/chapter11.html
  60. enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative };
  61. #ifdef use_int32
  62. typedef int cInt;
  63. typedef unsigned int cUInt;
  64. #else
  65. typedef signed long long cInt;
  66. typedef unsigned long long cUInt;
  67. #endif
  68. struct IntPoint {
  69. cInt X;
  70. cInt Y;
  71. #ifdef use_xyz
  72. cInt Z;
  73. IntPoint(cInt x = 0, cInt y = 0, cInt z = 0): X(x), Y(y), Z(z) {};
  74. #else
  75. IntPoint(cInt x = 0, cInt y = 0): X(x), Y(y) {};
  76. #endif
  77. friend inline bool operator== (const IntPoint& a, const IntPoint& b)
  78. {
  79. return a.X == b.X && a.Y == b.Y;
  80. }
  81. friend inline bool operator!= (const IntPoint& a, const IntPoint& b)
  82. {
  83. return a.X != b.X || a.Y != b.Y;
  84. }
  85. };
  86. //------------------------------------------------------------------------------
  87. typedef std::vector< IntPoint > Path;
  88. typedef std::vector< Path > Paths;
  89. inline Path& operator <<(Path& poly, const IntPoint& p) {poly.push_back(p); return poly;}
  90. inline Paths& operator <<(Paths& polys, const Path& p) {polys.push_back(p); return polys;}
  91. std::ostream& operator <<(std::ostream &s, const IntPoint &p);
  92. std::ostream& operator <<(std::ostream &s, const Path &p);
  93. std::ostream& operator <<(std::ostream &s, const Paths &p);
  94. struct DoublePoint
  95. {
  96. double X;
  97. double Y;
  98. DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {}
  99. DoublePoint(IntPoint ip) : X((double)ip.X), Y((double)ip.Y) {}
  100. };
  101. //------------------------------------------------------------------------------
  102. #ifdef use_xyz
  103. typedef void (*TZFillCallback)(IntPoint& z1, IntPoint& z2, IntPoint& pt);
  104. #endif
  105. enum InitOptions {ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4};
  106. enum JoinType {jtSquare, jtRound, jtMiter};
  107. enum EndType {etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound};
  108. #ifdef use_deprecated
  109. enum EndType_ {etClosed, etButt = 2, etSquare, etRound};
  110. #endif
  111. class PolyNode;
  112. typedef std::vector< PolyNode* > PolyNodes;
  113. class PolyNode
  114. {
  115. public:
  116. PolyNode();
  117. Path Contour;
  118. PolyNodes Childs;
  119. PolyNode* Parent;
  120. PolyNode* GetNext() const;
  121. bool IsHole() const;
  122. bool IsOpen() const;
  123. int ChildCount() const;
  124. private:
  125. unsigned Index; //node index in Parent.Childs
  126. bool m_IsOpen;
  127. JoinType m_jointype;
  128. EndType m_endtype;
  129. PolyNode* GetNextSiblingUp() const;
  130. void AddChild(PolyNode& child);
  131. friend class Clipper; //to access Index
  132. friend class ClipperOffset;
  133. };
  134. class PolyTree: public PolyNode
  135. {
  136. public:
  137. ~PolyTree(){Clear();};
  138. PolyNode* GetFirst() const;
  139. void Clear();
  140. int Total() const;
  141. private:
  142. PolyNodes AllNodes;
  143. friend class Clipper; //to access AllNodes
  144. };
  145. bool Orientation(const Path &poly);
  146. double Area(const Path &poly);
  147. int PointInPolygon(const IntPoint &pt, const Path &path);
  148. #ifdef use_deprecated
  149. void OffsetPaths(const Paths &in_polys, Paths &out_polys,
  150. double delta, JoinType jointype, EndType_ endtype, double limit = 0);
  151. #endif
  152. void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
  153. void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
  154. void SimplifyPolygons(Paths &polys, PolyFillType fillType = pftEvenOdd);
  155. void CleanPolygon(const Path& in_poly, Path& out_poly, double distance = 1.415);
  156. void CleanPolygon(Path& poly, double distance = 1.415);
  157. void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance = 1.415);
  158. void CleanPolygons(Paths& polys, double distance = 1.415);
  159. void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed);
  160. void MinkowskiSum(const Path& pattern, const Paths& paths,
  161. Paths& solution, PolyFillType pathFillType, bool pathIsClosed);
  162. void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution);
  163. void PolyTreeToPaths(const PolyTree& polytree, Paths& paths);
  164. void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths);
  165. void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths);
  166. void ReversePath(Path& p);
  167. void ReversePaths(Paths& p);
  168. struct IntRect { cInt left; cInt top; cInt right; cInt bottom; };
  169. //enums that are used internally ...
  170. enum EdgeSide { esLeft = 1, esRight = 2};
  171. //forward declarations (for stuff used internally) ...
  172. struct TEdge;
  173. struct IntersectNode;
  174. struct LocalMinima;
  175. struct Scanbeam;
  176. struct OutPt;
  177. struct OutRec;
  178. struct Join;
  179. typedef std::vector < OutRec* > PolyOutList;
  180. typedef std::vector < TEdge* > EdgeList;
  181. typedef std::vector < Join* > JoinList;
  182. typedef std::vector < IntersectNode* > IntersectList;
  183. //------------------------------------------------------------------------------
  184. //ClipperBase is the ancestor to the Clipper class. It should not be
  185. //instantiated directly. This class simply abstracts the conversion of sets of
  186. //polygon coordinates into edge objects that are stored in a LocalMinima list.
  187. class ClipperBase
  188. {
  189. public:
  190. ClipperBase();
  191. virtual ~ClipperBase();
  192. bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed);
  193. bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed);
  194. virtual void Clear();
  195. IntRect GetBounds();
  196. bool PreserveCollinear() {return m_PreserveCollinear;};
  197. void PreserveCollinear(bool value) {m_PreserveCollinear = value;};
  198. protected:
  199. void DisposeLocalMinimaList();
  200. TEdge* AddBoundsToLML(TEdge *e, bool IsClosed);
  201. void PopLocalMinima();
  202. virtual void Reset();
  203. TEdge* ProcessBound(TEdge* E, bool IsClockwise);
  204. void InsertLocalMinima(LocalMinima *newLm);
  205. void DoMinimaLML(TEdge* E1, TEdge* E2, bool IsClosed);
  206. TEdge* DescendToMin(TEdge *&E);
  207. void AscendToMax(TEdge *&E, bool Appending, bool IsClosed);
  208. LocalMinima *m_CurrentLM;
  209. LocalMinima *m_MinimaList;
  210. bool m_UseFullRange;
  211. EdgeList m_edges;
  212. bool m_PreserveCollinear;
  213. bool m_HasOpenPaths;
  214. };
  215. //------------------------------------------------------------------------------
  216. class Clipper : public virtual ClipperBase
  217. {
  218. public:
  219. Clipper(int initOptions = 0);
  220. ~Clipper();
  221. bool Execute(ClipType clipType,
  222. Paths &solution,
  223. PolyFillType subjFillType = pftEvenOdd,
  224. PolyFillType clipFillType = pftEvenOdd);
  225. bool Execute(ClipType clipType,
  226. PolyTree &polytree,
  227. PolyFillType subjFillType = pftEvenOdd,
  228. PolyFillType clipFillType = pftEvenOdd);
  229. bool ReverseSolution() {return m_ReverseOutput;};
  230. void ReverseSolution(bool value) {m_ReverseOutput = value;};
  231. bool StrictlySimple() {return m_StrictSimple;};
  232. void StrictlySimple(bool value) {m_StrictSimple = value;};
  233. //set the callback function for z value filling on intersections (otherwise Z is 0)
  234. #ifdef use_xyz
  235. void ZFillFunction(TZFillCallback zFillFunc);
  236. #endif
  237. protected:
  238. void Reset();
  239. virtual bool ExecuteInternal();
  240. private:
  241. PolyOutList m_PolyOuts;
  242. JoinList m_Joins;
  243. JoinList m_GhostJoins;
  244. IntersectList m_IntersectList;
  245. ClipType m_ClipType;
  246. std::set< cInt, std::greater<cInt> > m_Scanbeam;
  247. TEdge *m_ActiveEdges;
  248. TEdge *m_SortedEdges;
  249. bool m_ExecuteLocked;
  250. PolyFillType m_ClipFillType;
  251. PolyFillType m_SubjFillType;
  252. bool m_ReverseOutput;
  253. bool m_UsingPolyTree;
  254. bool m_StrictSimple;
  255. #ifdef use_xyz
  256. TZFillCallback m_ZFill; //custom callback
  257. #endif
  258. void SetWindingCount(TEdge& edge);
  259. bool IsEvenOddFillType(const TEdge& edge) const;
  260. bool IsEvenOddAltFillType(const TEdge& edge) const;
  261. void InsertScanbeam(const cInt Y);
  262. cInt PopScanbeam();
  263. void InsertLocalMinimaIntoAEL(const cInt botY);
  264. void InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge);
  265. void AddEdgeToSEL(TEdge *edge);
  266. void CopyAELToSEL();
  267. void DeleteFromSEL(TEdge *e);
  268. void DeleteFromAEL(TEdge *e);
  269. void UpdateEdgeIntoAEL(TEdge *&e);
  270. void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2);
  271. bool IsContributing(const TEdge& edge) const;
  272. bool IsTopHorz(const cInt XPos);
  273. void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2);
  274. void DoMaxima(TEdge *e);
  275. void PrepareHorzJoins(TEdge* horzEdge, bool isTopOfScanbeam);
  276. void ProcessHorizontals(bool IsTopOfScanbeam);
  277. void ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam);
  278. void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
  279. OutPt* AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
  280. OutRec* GetOutRec(int idx);
  281. void AppendPolygon(TEdge *e1, TEdge *e2);
  282. void IntersectEdges(TEdge *e1, TEdge *e2,
  283. const IntPoint &pt, bool protect = false);
  284. OutRec* CreateOutRec();
  285. OutPt* AddOutPt(TEdge *e, const IntPoint &pt);
  286. void DisposeAllOutRecs();
  287. void DisposeOutRec(PolyOutList::size_type index);
  288. bool ProcessIntersections(const cInt botY, const cInt topY);
  289. void BuildIntersectList(const cInt botY, const cInt topY);
  290. void ProcessIntersectList();
  291. void ProcessEdgesAtTopOfScanbeam(const cInt topY);
  292. void BuildResult(Paths& polys);
  293. void BuildResult2(PolyTree& polytree);
  294. void SetHoleState(TEdge *e, OutRec *outrec);
  295. void DisposeIntersectNodes();
  296. bool FixupIntersectionOrder();
  297. void FixupOutPolygon(OutRec &outrec);
  298. bool IsHole(TEdge *e);
  299. bool FindOwnerFromSplitRecs(OutRec &outRec, OutRec *&currOrfl);
  300. void FixHoleLinkage(OutRec &outrec);
  301. void AddJoin(OutPt *op1, OutPt *op2, const IntPoint offPt);
  302. void ClearJoins();
  303. void ClearGhostJoins();
  304. void AddGhostJoin(OutPt *op, const IntPoint offPt);
  305. bool JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2);
  306. void JoinCommonEdges();
  307. void DoSimplePolygons();
  308. void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec);
  309. void FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec);
  310. #ifdef use_xyz
  311. void SetZ(IntPoint& pt, TEdge& e);
  312. #endif
  313. };
  314. //------------------------------------------------------------------------------
  315. class ClipperOffset
  316. {
  317. public:
  318. ClipperOffset(double miterLimit = 2.0, double roundPrecision = 0.25);
  319. ~ClipperOffset();
  320. void AddPath(const Path& path, JoinType joinType, EndType endType);
  321. void AddPaths(const Paths& paths, JoinType joinType, EndType endType);
  322. void Execute(Paths& solution, double delta);
  323. void Execute(PolyTree& solution, double delta);
  324. void Clear();
  325. double MiterLimit;
  326. double ArcTolerance;
  327. private:
  328. Paths m_destPolys;
  329. Path m_srcPoly;
  330. Path m_destPoly;
  331. std::vector<DoublePoint> m_normals;
  332. double m_delta, m_sinA, m_sin, m_cos;
  333. double m_miterLim, m_StepsPerRad;
  334. IntPoint m_lowest;
  335. PolyNode m_polyNodes;
  336. void FixOrientations();
  337. void DoOffset(double delta);
  338. void OffsetPoint(int j, int& k, JoinType jointype);
  339. void DoSquare(int j, int k);
  340. void DoMiter(int j, int k, double r);
  341. void DoRound(int j, int k);
  342. };
  343. //------------------------------------------------------------------------------
  344. class clipperException : public std::exception
  345. {
  346. public:
  347. clipperException(const char* description): m_descr(description) {}
  348. virtual ~clipperException() throw() {}
  349. virtual const char* what() const throw() {return m_descr.c_str();}
  350. private:
  351. std::string m_descr;
  352. };
  353. //------------------------------------------------------------------------------
  354. } //ClipperLib namespace
  355. #endif //clipper_hpp