1
//----------------------------------------------------------------------------
2
// Anti-Grain Geometry - Version 2.4
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"
48
//================================================================conv_gpc
49
template<class VSA, class VSB> class conv_gpc
58
struct contour_header_type
65
typedef pod_bvector<gpc_vertex, 8> vertex_array_type;
66
typedef pod_bvector<contour_header_type, 6> contour_header_array_type;
70
typedef VSA source_a_type;
71
typedef VSB source_b_type;
72
typedef conv_gpc<source_a_type, source_b_type> self_type;
79
conv_gpc(source_a_type& a, source_b_type& b, gpc_op_e op = gpc_or) :
82
m_status(status_move_to),
87
memset(&m_poly_a, 0, sizeof(m_poly_a));
88
memset(&m_poly_b, 0, sizeof(m_poly_b));
89
memset(&m_result, 0, sizeof(m_result));
92
void attach1(VSA& source) { m_src_a = &source; }
93
void attach2(VSB& source) { m_src_b = &source; }
95
void operation(gpc_op_e v) { m_operation = v; }
97
// Vertex Source Interface
98
void rewind(unsigned path_id);
99
unsigned vertex(double* x, double* y);
102
conv_gpc(const conv_gpc<VSA, VSB>&);
103
const conv_gpc<VSA, VSB>& operator = (const conv_gpc<VSA, VSB>&);
105
//--------------------------------------------------------------------
106
void free_polygon(gpc_polygon& p);
108
void free_gpc_data();
109
void start_contour();
110
void add_vertex(double x, double y);
111
void end_contour(unsigned orientation);
112
void make_polygon(gpc_polygon& p);
113
void start_extracting();
115
bool next_vertex(double* x, double* y);
118
//--------------------------------------------------------------------
119
template<class VS> void add(VS& src, gpc_polygon& p)
123
double start_x = 0.0;
124
double start_y = 0.0;
125
bool line_to = false;
126
unsigned orientation = 0;
128
m_contour_accumulator.remove_all();
130
while(!is_stop(cmd = src.vertex(&x, &y)))
138
end_contour(orientation);
152
orientation = get_orientation(cmd);
153
if(line_to && is_closed(cmd))
155
add_vertex(start_x, start_y);
162
end_contour(orientation);
169
//--------------------------------------------------------------------
170
source_a_type* m_src_a;
171
source_b_type* m_src_b;
175
gpc_op_e m_operation;
176
vertex_array_type m_vertex_accumulator;
177
contour_header_array_type m_contour_accumulator;
178
gpc_polygon m_poly_a;
179
gpc_polygon m_poly_b;
180
gpc_polygon m_result;
187
//------------------------------------------------------------------------
188
template<class VSA, class VSB>
189
void conv_gpc<VSA, VSB>::free_polygon(gpc_polygon& p)
192
for(i = 0; i < p.num_contours; i++)
194
pod_allocator<gpc_vertex>::deallocate(p.contour[i].vertex,
195
p.contour[i].num_vertices);
197
pod_allocator<gpc_vertex_list>::deallocate(p.contour, p.num_contours);
198
memset(&p, 0, sizeof(gpc_polygon));
202
//------------------------------------------------------------------------
203
template<class VSA, class VSB>
204
void conv_gpc<VSA, VSB>::free_result()
208
gpc_free_polygon(&m_result);
210
memset(&m_result, 0, sizeof(m_result));
214
//------------------------------------------------------------------------
215
template<class VSA, class VSB>
216
void conv_gpc<VSA, VSB>::free_gpc_data()
218
free_polygon(m_poly_a);
219
free_polygon(m_poly_b);
224
//------------------------------------------------------------------------
225
template<class VSA, class VSB>
226
void conv_gpc<VSA, VSB>::start_contour()
228
contour_header_type h;
229
memset(&h, 0, sizeof(h));
230
m_contour_accumulator.add(h);
231
m_vertex_accumulator.remove_all();
235
//------------------------------------------------------------------------
236
template<class VSA, class VSB>
237
inline void conv_gpc<VSA, VSB>::add_vertex(double x, double y)
242
m_vertex_accumulator.add(v);
246
//------------------------------------------------------------------------
247
template<class VSA, class VSB>
248
void conv_gpc<VSA, VSB>::end_contour(unsigned orientation)
250
if(m_contour_accumulator.size())
252
if(m_vertex_accumulator.size() > 2)
254
contour_header_type& h =
255
m_contour_accumulator[m_contour_accumulator.size() - 1];
257
h.num_vertices = m_vertex_accumulator.size();
260
// TO DO: Clarify the "holes"
261
//if(is_cw(orientation)) h.hole_flag = 1;
263
h.vertices = pod_allocator<gpc_vertex>::allocate(h.num_vertices);
264
gpc_vertex* d = h.vertices;
266
for(i = 0; i < h.num_vertices; i++)
268
const gpc_vertex& s = m_vertex_accumulator[i];
276
m_vertex_accumulator.remove_last();
282
//------------------------------------------------------------------------
283
template<class VSA, class VSB>
284
void conv_gpc<VSA, VSB>::make_polygon(gpc_polygon& p)
287
if(m_contour_accumulator.size())
289
p.num_contours = m_contour_accumulator.size();
292
p.contour = pod_allocator<gpc_vertex_list>::allocate(p.num_contours);
295
gpc_vertex_list* pv = p.contour;
296
for(i = 0; i < p.num_contours; i++)
298
const contour_header_type& h = m_contour_accumulator[i];
299
pv->num_vertices = h.num_vertices;
300
pv->vertex = h.vertices;
307
//------------------------------------------------------------------------
308
template<class VSA, class VSB>
309
void conv_gpc<VSA, VSB>::start_extracting()
311
m_status = status_move_to;
317
//------------------------------------------------------------------------
318
template<class VSA, class VSB>
319
bool conv_gpc<VSA, VSB>::next_contour()
321
if(++m_contour < m_result.num_contours)
330
//------------------------------------------------------------------------
331
template<class VSA, class VSB>
332
inline bool conv_gpc<VSA, VSB>::next_vertex(double* x, double* y)
334
const gpc_vertex_list& vlist = m_result.contour[m_contour];
335
if(++m_vertex < vlist.num_vertices)
337
const gpc_vertex& v = vlist.vertex[m_vertex];
346
//------------------------------------------------------------------------
347
template<class VSA, class VSB>
348
void conv_gpc<VSA, VSB>::rewind(unsigned path_id)
351
m_src_a->rewind(path_id);
352
m_src_b->rewind(path_id);
353
add(*m_src_a, m_poly_a);
354
add(*m_src_b, m_poly_b);
358
gpc_polygon_clip(GPC_UNION,
365
gpc_polygon_clip(GPC_INT,
372
gpc_polygon_clip(GPC_XOR,
379
gpc_polygon_clip(GPC_DIFF,
386
gpc_polygon_clip(GPC_DIFF,
396
//------------------------------------------------------------------------
397
template<class VSA, class VSB>
398
unsigned conv_gpc<VSA, VSB>::vertex(double* x, double* y)
400
if(m_status == status_move_to)
404
if(next_vertex(x, y))
406
m_status = status_line_to;
407
return path_cmd_move_to;
409
m_status = status_stop;
410
return path_cmd_end_poly | path_flags_close;
415
if(next_vertex(x, y))
417
return path_cmd_line_to;
421
m_status = status_move_to;
423
return path_cmd_end_poly | path_flags_close;
425
return path_cmd_stop;