clipper.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. /*******************************************************************************
  2. * *
  3. * Author : Angus Johnson *
  4. * Version : 4.8.8 *
  5. * Date : 30 August 2012 *
  6. * Website : http://www.angusj.com *
  7. * Copyright : Angus Johnson 2010-2012 *
  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. #include <vector>
  36. #include <stdexcept>
  37. #include <cstring>
  38. #include <cstdlib>
  39. #include <ostream>
  40. namespace ClipperLib {
  41. enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor };
  42. enum PolyType { ptSubject, ptClip };
  43. //By far the most widely used winding rules for polygon filling are
  44. //EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32)
  45. //Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL)
  46. //see http://glprogramming.com/red/chapter11.html
  47. enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative };
  48. typedef signed long long long64;
  49. typedef unsigned long long ulong64;
  50. struct IntPoint {
  51. public:
  52. long64 X;
  53. long64 Y;
  54. IntPoint(long64 x = 0, long64 y = 0): X(x), Y(y) {};
  55. friend std::ostream& operator <<(std::ostream &s, IntPoint &p);
  56. };
  57. typedef std::vector< IntPoint > Polygon;
  58. typedef std::vector< Polygon > Polygons;
  59. std::ostream& operator <<(std::ostream &s, Polygon &p);
  60. std::ostream& operator <<(std::ostream &s, Polygons &p);
  61. struct ExPolygon {
  62. Polygon outer;
  63. Polygons holes;
  64. };
  65. typedef std::vector< ExPolygon > ExPolygons;
  66. enum JoinType { jtSquare, jtRound, jtMiter };
  67. bool Orientation(const Polygon &poly);
  68. double Area(const Polygon &poly);
  69. void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys,
  70. double delta, JoinType jointype = jtSquare, double MiterLimit = 2);
  71. void SimplifyPolygon(const Polygon &in_poly, Polygons &out_polys, PolyFillType fillType = pftEvenOdd);
  72. void SimplifyPolygons(const Polygons &in_polys, Polygons &out_polys, PolyFillType fillType = pftEvenOdd);
  73. void SimplifyPolygons(Polygons &polys, PolyFillType fillType = pftEvenOdd);
  74. void ReversePolygon(Polygon& p);
  75. void ReversePolygons(Polygons& p);
  76. //used internally ...
  77. enum EdgeSide { esNeither = 0, esLeft = 1, esRight = 2, esBoth = 3 };
  78. enum IntersectProtects { ipNone = 0, ipLeft = 1, ipRight = 2, ipBoth = 3 };
  79. struct TEdge {
  80. long64 xbot;
  81. long64 ybot;
  82. long64 xcurr;
  83. long64 ycurr;
  84. long64 xtop;
  85. long64 ytop;
  86. double dx;
  87. long64 tmpX;
  88. PolyType polyType;
  89. EdgeSide side;
  90. int windDelta; //1 or -1 depending on winding direction
  91. int windCnt;
  92. int windCnt2; //winding count of the opposite polytype
  93. int outIdx;
  94. TEdge *next;
  95. TEdge *prev;
  96. TEdge *nextInLML;
  97. TEdge *nextInAEL;
  98. TEdge *prevInAEL;
  99. TEdge *nextInSEL;
  100. TEdge *prevInSEL;
  101. };
  102. struct IntersectNode {
  103. TEdge *edge1;
  104. TEdge *edge2;
  105. IntPoint pt;
  106. IntersectNode *next;
  107. };
  108. struct LocalMinima {
  109. long64 Y;
  110. TEdge *leftBound;
  111. TEdge *rightBound;
  112. LocalMinima *next;
  113. };
  114. struct Scanbeam {
  115. long64 Y;
  116. Scanbeam *next;
  117. };
  118. struct OutPt; //forward declaration
  119. struct OutRec {
  120. int idx;
  121. bool isHole;
  122. OutRec *FirstLeft;
  123. OutRec *AppendLink;
  124. OutPt *pts;
  125. OutPt *bottomPt;
  126. OutPt *bottomFlag;
  127. EdgeSide sides;
  128. };
  129. struct OutPt {
  130. int idx;
  131. IntPoint pt;
  132. OutPt *next;
  133. OutPt *prev;
  134. };
  135. struct JoinRec {
  136. IntPoint pt1a;
  137. IntPoint pt1b;
  138. int poly1Idx;
  139. IntPoint pt2a;
  140. IntPoint pt2b;
  141. int poly2Idx;
  142. };
  143. struct HorzJoinRec {
  144. TEdge *edge;
  145. int savedIdx;
  146. };
  147. struct IntRect { long64 left; long64 top; long64 right; long64 bottom; };
  148. typedef std::vector < OutRec* > PolyOutList;
  149. typedef std::vector < TEdge* > EdgeList;
  150. typedef std::vector < JoinRec* > JoinList;
  151. typedef std::vector < HorzJoinRec* > HorzJoinList;
  152. //ClipperBase is the ancestor to the Clipper class. It should not be
  153. //instantiated directly. This class simply abstracts the conversion of sets of
  154. //polygon coordinates into edge objects that are stored in a LocalMinima list.
  155. class ClipperBase
  156. {
  157. public:
  158. ClipperBase();
  159. virtual ~ClipperBase();
  160. bool AddPolygon(const Polygon &pg, PolyType polyType);
  161. bool AddPolygons( const Polygons &ppg, PolyType polyType);
  162. virtual void Clear();
  163. IntRect GetBounds();
  164. protected:
  165. void DisposeLocalMinimaList();
  166. TEdge* AddBoundsToLML(TEdge *e);
  167. void PopLocalMinima();
  168. virtual void Reset();
  169. void InsertLocalMinima(LocalMinima *newLm);
  170. LocalMinima *m_CurrentLM;
  171. LocalMinima *m_MinimaList;
  172. bool m_UseFullRange;
  173. EdgeList m_edges;
  174. };
  175. class Clipper : public virtual ClipperBase
  176. {
  177. public:
  178. Clipper();
  179. ~Clipper();
  180. bool Execute(ClipType clipType,
  181. Polygons &solution,
  182. PolyFillType subjFillType = pftEvenOdd,
  183. PolyFillType clipFillType = pftEvenOdd);
  184. bool Execute(ClipType clipType,
  185. ExPolygons &solution,
  186. PolyFillType subjFillType = pftEvenOdd,
  187. PolyFillType clipFillType = pftEvenOdd);
  188. void Clear();
  189. bool ReverseSolution() {return m_ReverseOutput;};
  190. void ReverseSolution(bool value) {m_ReverseOutput = value;};
  191. protected:
  192. void Reset();
  193. virtual bool ExecuteInternal(bool fixHoleLinkages);
  194. private:
  195. PolyOutList m_PolyOuts;
  196. JoinList m_Joins;
  197. HorzJoinList m_HorizJoins;
  198. ClipType m_ClipType;
  199. Scanbeam *m_Scanbeam;
  200. TEdge *m_ActiveEdges;
  201. TEdge *m_SortedEdges;
  202. IntersectNode *m_IntersectNodes;
  203. bool m_ExecuteLocked;
  204. PolyFillType m_ClipFillType;
  205. PolyFillType m_SubjFillType;
  206. bool m_ReverseOutput;
  207. void DisposeScanbeamList();
  208. void SetWindingCount(TEdge& edge);
  209. bool IsEvenOddFillType(const TEdge& edge) const;
  210. bool IsEvenOddAltFillType(const TEdge& edge) const;
  211. void InsertScanbeam(const long64 Y);
  212. long64 PopScanbeam();
  213. void InsertLocalMinimaIntoAEL(const long64 botY);
  214. void InsertEdgeIntoAEL(TEdge *edge);
  215. void AddEdgeToSEL(TEdge *edge);
  216. void CopyAELToSEL();
  217. void DeleteFromSEL(TEdge *e);
  218. void DeleteFromAEL(TEdge *e);
  219. void UpdateEdgeIntoAEL(TEdge *&e);
  220. void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2);
  221. bool IsContributing(const TEdge& edge) const;
  222. bool IsTopHorz(const long64 XPos);
  223. void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2);
  224. void DoMaxima(TEdge *e, long64 topY);
  225. void ProcessHorizontals();
  226. void ProcessHorizontal(TEdge *horzEdge);
  227. void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
  228. void AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
  229. void AppendPolygon(TEdge *e1, TEdge *e2);
  230. void DoEdge1(TEdge *edge1, TEdge *edge2, const IntPoint &pt);
  231. void DoEdge2(TEdge *edge1, TEdge *edge2, const IntPoint &pt);
  232. void DoBothEdges(TEdge *edge1, TEdge *edge2, const IntPoint &pt);
  233. void IntersectEdges(TEdge *e1, TEdge *e2,
  234. const IntPoint &pt, IntersectProtects protects);
  235. OutRec* CreateOutRec();
  236. void AddOutPt(TEdge *e, const IntPoint &pt);
  237. void DisposeBottomPt(OutRec &outRec);
  238. void DisposeAllPolyPts();
  239. void DisposeOutRec(PolyOutList::size_type index);
  240. bool ProcessIntersections(const long64 botY, const long64 topY);
  241. void AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt);
  242. void BuildIntersectList(const long64 botY, const long64 topY);
  243. void ProcessIntersectList();
  244. void ProcessEdgesAtTopOfScanbeam(const long64 topY);
  245. void BuildResult(Polygons& polys);
  246. void BuildResultEx(ExPolygons& polys);
  247. void SetHoleState(TEdge *e, OutRec *OutRec);
  248. void DisposeIntersectNodes();
  249. bool FixupIntersections();
  250. void FixupOutPolygon(OutRec &outRec);
  251. bool IsHole(TEdge *e);
  252. void FixHoleLinkage(OutRec *outRec);
  253. void CheckHoleLinkages1(OutRec *outRec1, OutRec *outRec2);
  254. void CheckHoleLinkages2(OutRec *outRec1, OutRec *outRec2);
  255. void AddJoin(TEdge *e1, TEdge *e2, int e1OutIdx = -1, int e2OutIdx = -1);
  256. void ClearJoins();
  257. void AddHorzJoin(TEdge *e, int idx);
  258. void ClearHorzJoins();
  259. void JoinCommonEdges(bool fixHoleLinkages);
  260. };
  261. //------------------------------------------------------------------------------
  262. //------------------------------------------------------------------------------
  263. class clipperException : public std::exception
  264. {
  265. public:
  266. clipperException(const char* description): m_descr(description) {}
  267. virtual ~clipperException() throw() {}
  268. virtual const char* what() const throw() {return m_descr.c_str();}
  269. private:
  270. std::string m_descr;
  271. };
  272. //------------------------------------------------------------------------------
  273. } //ClipperLib namespace
  274. #endif //clipper_hpp