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