1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.3
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
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.
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
28 #include "agg_basics.h"
29 #include "agg_array.h"
30 #include "agg_vertex_iterator.h"
49 //================================================================conv_gpc
50 template<class VSA
, class VSB
> class conv_gpc
59 struct contour_header_type
66 typedef pod_deque
<gpc_vertex
, 8> vertex_array_type
;
67 typedef pod_deque
<contour_header_type
, 6> contour_header_array_type
;
71 typedef VSA source_a_type
;
72 typedef VSB source_b_type
;
73 typedef conv_gpc
<source_a_type
, source_b_type
> self_type
;
80 conv_gpc(source_a_type
& a
, source_b_type
& b
, gpc_op_e op
= gpc_or
) :
83 m_status(status_move_to
),
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
);
103 typedef vertex_iterator
<self_type
> iterator
;
104 iterator
begin(unsigned id
) { return iterator(*this, id
); }
105 iterator
end() { return iterator(path_cmd_stop
); }
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
);
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();
121 bool next_vertex(double* x
, double* y
);
124 //--------------------------------------------------------------------
125 template<class VS
> void add(VS
& src
, gpc_polygon
& p
)
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
)))
144 end_contour(orientation
);
158 orientation
= get_orientation(cmd
);
159 if(line_to
&& is_closed(cmd
))
161 add_vertex(start_x
, start_y
);
168 end_contour(orientation
);
175 //--------------------------------------------------------------------
176 source_a_type
* m_src_a
;
177 source_b_type
* m_src_b
;
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
)
198 for(i
= 0; i
< p
.num_contours
; i
++)
200 delete [] p
.contour
[i
].vertex
;
204 memset(&p
, 0, sizeof(gpc_polygon
));
208 //------------------------------------------------------------------------
209 template<class VSA
, class VSB
>
210 void conv_gpc
<VSA
, VSB
>::free_result()
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
);
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
)
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();
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
;
272 for(i
= 0; i
< h
.num_vertices
; i
++)
274 const gpc_vertex
& s
= m_vertex_accumulator
[i
];
282 m_vertex_accumulator
.remove_last();
288 //------------------------------------------------------------------------
289 template<class VSA
, class VSB
>
290 void conv_gpc
<VSA
, VSB
>::make_polygon(gpc_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];
301 p
.contour
= new gpc_vertex_list
[p
.num_contours
];
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
;
318 //------------------------------------------------------------------------
319 template<class VSA
, class VSB
>
320 void conv_gpc
<VSA
, VSB
>::start_extracting()
322 m_status
= status_move_to
;
328 //------------------------------------------------------------------------
329 template<class VSA
, class VSB
>
330 bool conv_gpc
<VSA
, VSB
>::next_contour()
332 if(++m_contour
< m_result
.num_contours
)
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
];
357 //------------------------------------------------------------------------
358 template<class VSA
, class VSB
>
359 void conv_gpc
<VSA
, VSB
>::rewind(unsigned id
)
364 add(*m_src_a
, m_poly_a
);
365 add(*m_src_b
, m_poly_b
);
369 gpc_polygon_clip(GPC_UNION
,
376 gpc_polygon_clip(GPC_INT
,
383 gpc_polygon_clip(GPC_XOR
,
390 gpc_polygon_clip(GPC_DIFF
,
397 gpc_polygon_clip(GPC_DIFF
,
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
)
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
;
426 if(next_vertex(x
, y
))
428 return path_cmd_line_to
;
432 m_status
= status_move_to
;
434 return path_cmd_end_poly
| path_flags_close
;
436 return path_cmd_stop
;