1
/*******************************************************************************
3
* Author : Angus Johnson *
5
* Date : 4 April 2011 *
6
* Website : http://www.angusj.com *
7
* Copyright : Angus Johnson 2010-2011 *
10
* Use, modification & distribution is subject to Boost Software License Ver 1. *
11
* http://www.boost.org/LICENSE_1_0.txt *
13
*******************************************************************************/
15
#ifndef AGG_CONV_CLIPPER_INCLUDED
16
#define AGG_CONV_CLIPPER_INCLUDED
19
#include "agg_basics.h"
20
#include "agg_array.h"
21
#include "clipper.hpp"
25
enum clipper_op_e { clipper_or,
26
clipper_and, clipper_xor, clipper_a_minus_b, clipper_b_minus_a };
27
enum clipper_PolyFillType {clipper_even_odd, clipper_non_zero};
29
template<class VSA, class VSB> class conv_clipper
31
enum status { status_move_to, status_line_to, status_stop };
32
typedef VSA source_a_type;
33
typedef VSB source_b_type;
34
typedef conv_clipper<source_a_type, source_b_type> self_type;
37
source_a_type* m_src_a;
38
source_b_type* m_src_b;
43
clipper_op_e m_operation;
44
pod_bvector<clipper::IntPoint, 8> m_vertex_accumulator;
45
clipper::Polygons m_poly_a;
46
clipper::Polygons m_poly_b;
47
clipper::Polygons m_result;
48
clipper::Clipper m_clipper;
49
clipper_PolyFillType m_subjFillType;
50
clipper_PolyFillType m_clipFillType;
54
if ((val < 0)) return (int)(val - 0.5); else return (int)(val + 0.5);
58
conv_clipper(source_a_type &a, source_b_type &b,
59
clipper_op_e op = clipper_or,
60
clipper_PolyFillType subjFillType = clipper_even_odd,
61
clipper_PolyFillType clipFillType = clipper_even_odd,
62
int scaling_factor = 2) :
65
m_status(status_move_to),
69
m_subjFillType(subjFillType),
70
m_clipFillType(clipFillType)
72
m_scaling_factor = std::max(std::min(scaling_factor, 6),0);
73
m_scaling_factor = Round(std::pow((double)10, m_scaling_factor));
80
void attach1(VSA &source, clipper_PolyFillType subjFillType = clipper_even_odd)
81
{ m_src_a = &source; m_subjFillType = subjFillType; }
82
void attach2(VSB &source, clipper_PolyFillType clipFillType = clipper_even_odd)
83
{ m_src_b = &source; m_clipFillType = clipFillType; }
85
void operation(clipper_op_e v) { m_operation = v; }
87
void rewind(unsigned path_id);
88
unsigned vertex(double* x, double* y);
91
bool next_vertex(double* x, double* y);
92
void start_extracting();
93
void add_vertex_(double &x, double &y);
94
void end_contour(clipper::Polygons &p);
96
template<class VS> void add(VS &src, clipper::Polygons &p){
98
double x; double y; double start_x; double start_y;
99
bool starting_first_line;
103
starting_first_line = true;
106
cmd = src->vertex( &x , &y );
113
if(!starting_first_line ) end_contour(p);
118
starting_first_line = false;
120
else if(is_end_poly(cmd))
122
if(!starting_first_line && is_closed(cmd))
123
add_vertex_( start_x, start_y );
125
cmd = src->vertex( &x, &y );
131
//------------------------------------------------------------------------
133
template<class VSA, class VSB>
134
void conv_clipper<VSA, VSB>::start_extracting()
136
m_status = status_move_to;
140
//------------------------------------------------------------------------------
142
template<class VSA, class VSB>
143
void conv_clipper<VSA, VSB>::rewind(unsigned path_id)
145
m_src_a->rewind( path_id );
146
m_src_b->rewind( path_id );
148
add( m_src_a , m_poly_a );
149
add( m_src_b , m_poly_b );
152
clipper::PolyFillType pftSubj = (m_subjFillType == clipper_even_odd) ?
153
clipper::pftEvenOdd : clipper::pftNonZero;
154
clipper::PolyFillType pftClip = (m_clipFillType == clipper_even_odd) ?
155
clipper::pftEvenOdd : clipper::pftNonZero;
158
switch( m_operation ) {
161
m_clipper.AddPolygons( m_poly_a , clipper::ptSubject );
162
m_clipper.AddPolygons( m_poly_b , clipper::ptClip );
163
m_clipper.Execute( clipper::ctUnion , m_result , pftSubj, pftClip);
168
m_clipper.AddPolygons( m_poly_a , clipper::ptSubject );
169
m_clipper.AddPolygons( m_poly_b , clipper::ptClip );
170
m_clipper.Execute( clipper::ctIntersection , m_result, pftSubj, pftClip );
175
m_clipper.AddPolygons( m_poly_a , clipper::ptSubject );
176
m_clipper.AddPolygons( m_poly_b , clipper::ptClip );
177
m_clipper.Execute( clipper::ctXor , m_result, pftSubj, pftClip );
180
case clipper_a_minus_b:
182
m_clipper.AddPolygons( m_poly_a , clipper::ptSubject );
183
m_clipper.AddPolygons( m_poly_b , clipper::ptClip );
184
m_clipper.Execute( clipper::ctDifference , m_result, pftSubj, pftClip );
187
case clipper_b_minus_a:
189
m_clipper.AddPolygons( m_poly_b , clipper::ptSubject );
190
m_clipper.AddPolygons( m_poly_a , clipper::ptClip );
191
m_clipper.Execute( clipper::ctDifference , m_result, pftSubj, pftClip );
197
//------------------------------------------------------------------------------
199
template<class VSA, class VSB>
200
void conv_clipper<VSA, VSB>::end_contour( clipper::Polygons &p)
204
if( m_vertex_accumulator.size() < 3 ) return;
207
p[len].resize(m_vertex_accumulator.size());
208
for( i = 0 ; i < m_vertex_accumulator.size() ; i++ )
209
p[len][i] = m_vertex_accumulator[i];
210
m_vertex_accumulator.remove_all();
212
//------------------------------------------------------------------------------
214
template<class VSA, class VSB>
215
void conv_clipper<VSA, VSB>::add_vertex_(double &x, double &y)
219
v.X = Round(x * m_scaling_factor);
220
v.Y = Round(y * m_scaling_factor);
221
m_vertex_accumulator.add( v );
223
//------------------------------------------------------------------------------
225
template<class VSA, class VSB>
226
bool conv_clipper<VSA, VSB>::next_contour()
229
if(m_contour >= (int)m_result.size()) return false;
233
//------------------------------------------------------------------------------
235
template<class VSA, class VSB>
236
bool conv_clipper<VSA, VSB>::next_vertex(double *x, double *y)
239
if(m_vertex >= (int)m_result[m_contour].size()) return false;
240
*x = (double)m_result[ m_contour ][ m_vertex ].X / m_scaling_factor;
241
*y = (double)m_result[ m_contour ][ m_vertex ].Y / m_scaling_factor;
244
//------------------------------------------------------------------------------
246
template<class VSA, class VSB>
247
unsigned conv_clipper<VSA, VSB>::vertex(double *x, double *y)
249
if( m_status == status_move_to )
253
if( next_vertex( x, y ) )
255
m_status =status_line_to;
256
return path_cmd_move_to;
260
m_status = status_stop;
261
return path_cmd_end_poly | path_flags_close;
265
return path_cmd_stop;
269
if( next_vertex( x, y ) )
271
return path_cmd_line_to;
275
m_status = status_move_to;
276
return path_cmd_end_poly | path_flags_close;
280
//------------------------------------------------------------------------------
284
#endif //AGG_CONV_CLIPPER_INCLUDED