update dev300-m57
[ooovba.git] / agg / inc / agg_conv_gpc.h
blob8064a0a1451e03f6249bda22d0f14b4abd213a96
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.3
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 //
5 // Permission to copy, use, modify, sell and distribute this software
6 // is granted provided this copyright notice appears in all copies.
7 // This software is provided "as is" without express or implied
8 // warranty, and with no claim as to its suitability for any purpose.
9 //
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 // mcseemagg@yahoo.com
13 // http://www.antigrain.com
14 //----------------------------------------------------------------------------
16 // General Polygon Clipper based on the GPC library by Alan Murta
17 // Union, Intersection, XOR, A-B, B-A
18 // Contact the author if you intend to use it in commercial applications!
19 // http://www.cs.man.ac.uk/aig/staff/alan/software/
20 // Alan Murta (email: gpc@cs.man.ac.uk)
22 //----------------------------------------------------------------------------
24 #ifndef AGG_CONV_GPC_INCLUDED
25 #define AGG_CONV_GPC_INCLUDED
27 #include <math.h>
28 #include "agg_basics.h"
29 #include "agg_array.h"
30 #include "agg_vertex_iterator.h"
32 extern "C"
34 #include "gpc.h"
37 namespace agg
39 enum gpc_op_e
41 gpc_or,
42 gpc_and,
43 gpc_xor,
44 gpc_a_minus_b,
45 gpc_b_minus_a
49 //================================================================conv_gpc
50 template<class VSA, class VSB> class conv_gpc
52 enum status
54 status_move_to,
55 status_line_to,
56 status_stop
59 struct contour_header_type
61 int num_vertices;
62 int hole_flag;
63 gpc_vertex* vertices;
66 typedef pod_deque<gpc_vertex, 8> vertex_array_type;
67 typedef pod_deque<contour_header_type, 6> contour_header_array_type;
70 public:
71 typedef VSA source_a_type;
72 typedef VSB source_b_type;
73 typedef conv_gpc<source_a_type, source_b_type> self_type;
75 ~conv_gpc()
77 free_gpc_data();
80 conv_gpc(source_a_type& a, source_b_type& b, gpc_op_e op = gpc_or) :
81 m_src_a(&a),
82 m_src_b(&b),
83 m_status(status_move_to),
84 m_vertex(-1),
85 m_contour(-1),
86 m_operation(op)
88 memset(&m_poly_a, 0, sizeof(m_poly_a));
89 memset(&m_poly_b, 0, sizeof(m_poly_b));
90 memset(&m_result, 0, sizeof(m_result));
93 void set_source1(VSA& source) { m_src_a = &source; }
94 void set_source2(VSB& source) { m_src_b = &source; }
96 void operation(gpc_op_e v) { m_operation = v; }
98 // Vertex Source Interface
99 void rewind(unsigned id);
100 unsigned vertex(double* x, double* y);
102 // Iterator
103 typedef vertex_iterator<self_type> iterator;
104 iterator begin(unsigned id) { return iterator(*this, id); }
105 iterator end() { return iterator(path_cmd_stop); }
107 private:
108 conv_gpc(const conv_gpc<VSA, VSB>&);
109 const conv_gpc<VSA, VSB>& operator = (const conv_gpc<VSA, VSB>&);
111 //--------------------------------------------------------------------
112 void free_polygon(gpc_polygon& p);
113 void free_result();
114 void free_gpc_data();
115 void start_contour();
116 void add_vertex(double x, double y);
117 void end_contour(unsigned orientation);
118 void make_polygon(gpc_polygon& p);
119 void start_extracting();
120 bool next_contour();
121 bool next_vertex(double* x, double* y);
124 //--------------------------------------------------------------------
125 template<class VS> void add(VS& src, gpc_polygon& p)
127 unsigned cmd;
128 double x, y;
129 double start_x = 0.0;
130 double start_y = 0.0;
131 bool line_to = false;
132 unsigned orientation = 0;
134 m_contour_accumulator.remove_all();
136 while(!is_stop(cmd = src.vertex(&x, &y)))
138 if(is_vertex(cmd))
140 if(is_move_to(cmd))
142 if(line_to)
144 end_contour(orientation);
145 orientation = 0;
147 start_contour();
148 start_x = x;
149 start_y = y;
151 add_vertex(x, y);
152 line_to = true;
154 else
156 if(is_end_poly(cmd))
158 orientation = get_orientation(cmd);
159 if(line_to && is_closed(cmd))
161 add_vertex(start_x, start_y);
166 if(line_to)
168 end_contour(orientation);
170 make_polygon(p);
174 private:
175 //--------------------------------------------------------------------
176 source_a_type* m_src_a;
177 source_b_type* m_src_b;
178 status m_status;
179 int m_vertex;
180 int m_contour;
181 gpc_op_e m_operation;
182 vertex_array_type m_vertex_accumulator;
183 contour_header_array_type m_contour_accumulator;
184 gpc_polygon m_poly_a;
185 gpc_polygon m_poly_b;
186 gpc_polygon m_result;
193 //------------------------------------------------------------------------
194 template<class VSA, class VSB>
195 void conv_gpc<VSA, VSB>::free_polygon(gpc_polygon& p)
197 int i;
198 for(i = 0; i < p.num_contours; i++)
200 delete [] p.contour[i].vertex;
202 delete [] p.hole;
203 delete [] p.contour;
204 memset(&p, 0, sizeof(gpc_polygon));
208 //------------------------------------------------------------------------
209 template<class VSA, class VSB>
210 void conv_gpc<VSA, VSB>::free_result()
212 if(m_result.contour)
214 gpc_free_polygon(&m_result);
216 memset(&m_result, 0, sizeof(m_result));
220 //------------------------------------------------------------------------
221 template<class VSA, class VSB>
222 void conv_gpc<VSA, VSB>::free_gpc_data()
224 free_polygon(m_poly_a);
225 free_polygon(m_poly_b);
226 free_result();
230 //------------------------------------------------------------------------
231 template<class VSA, class VSB>
232 void conv_gpc<VSA, VSB>::start_contour()
234 contour_header_type h;
235 memset(&h, 0, sizeof(h));
236 m_contour_accumulator.add(h);
237 m_vertex_accumulator.remove_all();
241 //------------------------------------------------------------------------
242 template<class VSA, class VSB>
243 inline void conv_gpc<VSA, VSB>::add_vertex(double x, double y)
245 gpc_vertex v;
246 v.x = x;
247 v.y = y;
248 m_vertex_accumulator.add(v);
252 //------------------------------------------------------------------------
253 template<class VSA, class VSB>
254 void conv_gpc<VSA, VSB>::end_contour(unsigned orientation)
256 if(m_contour_accumulator.size())
258 if(m_vertex_accumulator.size() > 2)
260 contour_header_type& h =
261 m_contour_accumulator[m_contour_accumulator.size() - 1];
263 h.num_vertices = m_vertex_accumulator.size();
264 h.hole_flag = 0;
266 // TO DO: Clarify the "holes"
267 //if(is_cw(orientation)) h.hole_flag = 1;
269 h.vertices = new gpc_vertex [h.num_vertices];
270 gpc_vertex* d = h.vertices;
271 int i;
272 for(i = 0; i < h.num_vertices; i++)
274 const gpc_vertex& s = m_vertex_accumulator[i];
275 d->x = s.x;
276 d->y = s.y;
277 ++d;
280 else
282 m_vertex_accumulator.remove_last();
288 //------------------------------------------------------------------------
289 template<class VSA, class VSB>
290 void conv_gpc<VSA, VSB>::make_polygon(gpc_polygon& p)
292 free_polygon(p);
293 if(m_contour_accumulator.size())
295 p.num_contours = m_contour_accumulator.size();
297 // TO DO: Clarify the "holes"
298 //p.hole = new int[p.num_contours];
299 p.hole = 0;
301 p.contour = new gpc_vertex_list[p.num_contours];
303 int i;
304 //int* ph = p.hole;
305 gpc_vertex_list* pv = p.contour;
306 for(i = 0; i < p.num_contours; i++)
308 const contour_header_type& h = m_contour_accumulator[i];
309 // *ph++ = h.hole_flag;
310 pv->num_vertices = h.num_vertices;
311 pv->vertex = h.vertices;
312 ++pv;
318 //------------------------------------------------------------------------
319 template<class VSA, class VSB>
320 void conv_gpc<VSA, VSB>::start_extracting()
322 m_status = status_move_to;
323 m_contour = -1;
324 m_vertex = -1;
328 //------------------------------------------------------------------------
329 template<class VSA, class VSB>
330 bool conv_gpc<VSA, VSB>::next_contour()
332 if(++m_contour < m_result.num_contours)
334 m_vertex = -1;
335 return true;
337 return false;
341 //------------------------------------------------------------------------
342 template<class VSA, class VSB>
343 inline bool conv_gpc<VSA, VSB>::next_vertex(double* x, double* y)
345 const gpc_vertex_list& vlist = m_result.contour[m_contour];
346 if(++m_vertex < vlist.num_vertices)
348 const gpc_vertex& v = vlist.vertex[m_vertex];
349 *x = v.x;
350 *y = v.y;
351 return true;
353 return false;
357 //------------------------------------------------------------------------
358 template<class VSA, class VSB>
359 void conv_gpc<VSA, VSB>::rewind(unsigned id)
361 free_result();
362 m_src_a->rewind(id);
363 m_src_b->rewind(id);
364 add(*m_src_a, m_poly_a);
365 add(*m_src_b, m_poly_b);
366 switch(m_operation)
368 case gpc_or:
369 gpc_polygon_clip(GPC_UNION,
370 &m_poly_a,
371 &m_poly_b,
372 &m_result);
373 break;
375 case gpc_and:
376 gpc_polygon_clip(GPC_INT,
377 &m_poly_a,
378 &m_poly_b,
379 &m_result);
380 break;
382 case gpc_xor:
383 gpc_polygon_clip(GPC_XOR,
384 &m_poly_a,
385 &m_poly_b,
386 &m_result);
387 break;
389 case gpc_a_minus_b:
390 gpc_polygon_clip(GPC_DIFF,
391 &m_poly_a,
392 &m_poly_b,
393 &m_result);
394 break;
396 case gpc_b_minus_a:
397 gpc_polygon_clip(GPC_DIFF,
398 &m_poly_b,
399 &m_poly_a,
400 &m_result);
401 break;
403 start_extracting();
407 //------------------------------------------------------------------------
408 template<class VSA, class VSB>
409 unsigned conv_gpc<VSA, VSB>::vertex(double* x, double* y)
411 if(m_status == status_move_to)
413 if(next_contour())
415 if(next_vertex(x, y))
417 m_status = status_line_to;
418 return path_cmd_move_to;
420 m_status = status_stop;
421 return path_cmd_end_poly | path_flags_close;
424 else
426 if(next_vertex(x, y))
428 return path_cmd_line_to;
430 else
432 m_status = status_move_to;
434 return path_cmd_end_poly | path_flags_close;
436 return path_cmd_stop;
443 #endif