+ initialize x,y for close_path commands

This commit is contained in:
artemp 2013-02-22 15:02:10 +00:00
parent 1b3b598b80
commit 21c618ccc5

View file

@ -23,287 +23,301 @@
namespace agg namespace agg
{ {
enum clipper_op_e { clipper_or, enum clipper_op_e { clipper_or,
clipper_and, clipper_xor, clipper_a_minus_b, clipper_b_minus_a }; clipper_and, clipper_xor, clipper_a_minus_b, clipper_b_minus_a };
enum clipper_PolyFillType {clipper_even_odd, clipper_non_zero, clipper_positive, clipper_negative}; enum clipper_PolyFillType {clipper_even_odd, clipper_non_zero, clipper_positive, clipper_negative};
template<class VSA, class VSB> class conv_clipper template<class VSA, class VSB> class conv_clipper
{ {
enum status { status_move_to, status_line_to, status_stop }; enum status { status_move_to, status_line_to, status_stop };
typedef VSA source_a_type; typedef VSA source_a_type;
typedef VSB source_b_type; typedef VSB source_b_type;
typedef conv_clipper<source_a_type, source_b_type> self_type; typedef conv_clipper<source_a_type, source_b_type> self_type;
private: private:
source_a_type* m_src_a; source_a_type* m_src_a;
source_b_type* m_src_b; source_b_type* m_src_b;
status m_status; status m_status;
int m_vertex; int m_vertex;
int m_contour; int m_contour;
int m_scaling_factor; int m_scaling_factor;
clipper_op_e m_operation; clipper_op_e m_operation;
pod_bvector<ClipperLib::IntPoint, 8> m_vertex_accumulator; pod_bvector<ClipperLib::IntPoint, 8> m_vertex_accumulator;
ClipperLib::Polygons m_poly_a; ClipperLib::Polygons m_poly_a;
ClipperLib::Polygons m_poly_b; ClipperLib::Polygons m_poly_b;
ClipperLib::Polygons m_result; ClipperLib::Polygons m_result;
ClipperLib::Clipper m_clipper; ClipperLib::Clipper m_clipper;
clipper_PolyFillType m_subjFillType; clipper_PolyFillType m_subjFillType;
clipper_PolyFillType m_clipFillType; clipper_PolyFillType m_clipFillType;
double start_x_;
double start_y_;
int Round(double val) int Round(double val)
{ {
if ((val < 0)) return (int)(val - 0.5); else return (int)(val + 0.5); if ((val < 0)) return (int)(val - 0.5); else return (int)(val + 0.5);
} }
public: public:
conv_clipper(source_a_type &a, source_b_type &b, conv_clipper(source_a_type &a, source_b_type &b,
clipper_op_e op = clipper_or, clipper_op_e op = clipper_or,
clipper_PolyFillType subjFillType = clipper_even_odd, clipper_PolyFillType subjFillType = clipper_even_odd,
clipper_PolyFillType clipFillType = clipper_even_odd, clipper_PolyFillType clipFillType = clipper_even_odd,
int scaling_factor = 2) : int scaling_factor = 2) :
m_src_a(&a), m_src_a(&a),
m_src_b(&b), m_src_b(&b),
m_status(status_move_to), m_status(status_move_to),
m_vertex(-1), m_vertex(-1),
m_contour(-1), m_contour(-1),
m_operation(op), m_operation(op),
m_subjFillType(subjFillType), m_subjFillType(subjFillType),
m_clipFillType(clipFillType) m_clipFillType(clipFillType),
{ start_x_(0),
m_scaling_factor = std::max(std::min(scaling_factor, 6),0); start_y_(0)
m_scaling_factor = Round(std::pow((double)10, m_scaling_factor)); {
} m_scaling_factor = std::max(std::min(scaling_factor, 6),0);
m_scaling_factor = Round(std::pow((double)10, m_scaling_factor));
}
conv_clipper(source_a_type &a, conv_clipper(source_a_type &a,
clipper_op_e op = clipper_and, clipper_op_e op = clipper_and,
clipper_PolyFillType subjFillType = clipper_non_zero, clipper_PolyFillType subjFillType = clipper_non_zero,
clipper_PolyFillType clipFillType = clipper_non_zero, clipper_PolyFillType clipFillType = clipper_non_zero,
int scaling_factor = 6) : int scaling_factor = 6) :
m_src_a(&a), m_src_a(&a),
m_status(status_move_to), m_status(status_move_to),
m_vertex(-1), m_vertex(-1),
m_contour(-1), m_contour(-1),
m_operation(op), m_operation(op),
m_subjFillType(subjFillType), m_subjFillType(subjFillType),
m_clipFillType(clipFillType) m_clipFillType(clipFillType),
{ start_x_(0),
m_scaling_factor = std::max(std::min(scaling_factor, 6),0); start_y_(0)
m_scaling_factor = Round(std::pow((double)10, m_scaling_factor)); {
} m_scaling_factor = std::max(std::min(scaling_factor, 6),0);
m_scaling_factor = Round(std::pow((double)10, m_scaling_factor));
}
~conv_clipper() ~conv_clipper()
{ {
} }
unsigned type() const { return m_src_a->type(); } unsigned type() const { return m_src_a->type(); }
void attach1(VSA &source, clipper_PolyFillType subjFillType = clipper_even_odd) void attach1(VSA &source, clipper_PolyFillType subjFillType = clipper_even_odd)
{ m_src_a = &source; m_subjFillType = subjFillType; } { m_src_a = &source; m_subjFillType = subjFillType; }
void attach2(VSB &source, clipper_PolyFillType clipFillType = clipper_even_odd) void attach2(VSB &source, clipper_PolyFillType clipFillType = clipper_even_odd)
{ m_src_b = &source; m_clipFillType = clipFillType; } { m_src_b = &source; m_clipFillType = clipFillType; }
void operation(clipper_op_e v) { m_operation = v; } void operation(clipper_op_e v) { m_operation = v; }
void rewind(unsigned path_id); void rewind(unsigned path_id);
unsigned vertex(double* x, double* y); unsigned vertex(double* x, double* y);
bool next_contour(); bool next_contour();
bool next_vertex(double* x, double* y); bool next_vertex(double* x, double* y);
void start_extracting(); void start_extracting();
void add_vertex_(double &x, double &y); void add_vertex_(double &x, double &y);
void end_contour(ClipperLib::Polygons &p); void end_contour(ClipperLib::Polygons &p);
template<class VS> void add(VS &src, ClipperLib::Polygons &p){ template<class VS> void add(VS &src, ClipperLib::Polygons &p){
unsigned cmd; unsigned cmd;
double x; double y; double start_x; double start_y; double x; double y; double start_x; double start_y;
bool starting_first_line; bool starting_first_line;
start_x = 0.0; start_x = 0.0;
start_y = 0.0; start_y = 0.0;
starting_first_line = true; starting_first_line = true;
p.resize(0); p.resize(0);
cmd = src->vertex( &x , &y ); cmd = src->vertex( &x , &y );
while(!is_stop(cmd)) while(!is_stop(cmd))
{ {
if(is_vertex(cmd)) if(is_vertex(cmd))
{ {
if(is_move_to(cmd)) if(is_move_to(cmd))
{ {
if(!starting_first_line ) end_contour(p); if(!starting_first_line ) end_contour(p);
start_x = x; start_x = x;
start_y = y; start_y = y;
} }
add_vertex_( x, y ); add_vertex_( x, y );
starting_first_line = false; starting_first_line = false;
} }
else if(is_end_poly(cmd)) else if(is_end_poly(cmd))
{ {
if(!starting_first_line && is_closed(cmd)) if(!starting_first_line && is_closed(cmd))
add_vertex_( start_x, start_y ); add_vertex_( start_x, start_y );
} }
cmd = src->vertex( &x, &y ); cmd = src->vertex( &x, &y );
} }
end_contour(p); end_contour(p);
} }
}; };
//------------------------------------------------------------------------ //------------------------------------------------------------------------
template<class VSA, class VSB> template<class VSA, class VSB>
void conv_clipper<VSA, VSB>::start_extracting() void conv_clipper<VSA, VSB>::start_extracting()
{ {
m_status = status_move_to; m_status = status_move_to;
m_contour = -1; m_contour = -1;
m_vertex = -1; m_vertex = -1;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template<class VSA, class VSB> template<class VSA, class VSB>
void conv_clipper<VSA, VSB>::rewind(unsigned path_id) void conv_clipper<VSA, VSB>::rewind(unsigned path_id)
{ {
m_src_a->rewind( path_id ); m_src_a->rewind( path_id );
m_src_b->rewind( path_id ); m_src_b->rewind( path_id );
add( m_src_a , m_poly_a ); add( m_src_a , m_poly_a );
add( m_src_b , m_poly_b ); add( m_src_b , m_poly_b );
m_result.resize(0); m_result.resize(0);
ClipperLib::PolyFillType pftSubj, pftClip; ClipperLib::PolyFillType pftSubj, pftClip;
switch (m_subjFillType) switch (m_subjFillType)
{ {
case clipper_even_odd: pftSubj = ClipperLib::pftEvenOdd; break; case clipper_even_odd: pftSubj = ClipperLib::pftEvenOdd; break;
case clipper_non_zero: pftSubj = ClipperLib::pftNonZero; break; case clipper_non_zero: pftSubj = ClipperLib::pftNonZero; break;
case clipper_positive: pftSubj = ClipperLib::pftPositive; break; case clipper_positive: pftSubj = ClipperLib::pftPositive; break;
default: pftSubj = ClipperLib::pftNegative; default: pftSubj = ClipperLib::pftNegative;
} }
switch (m_clipFillType) switch (m_clipFillType)
{ {
case clipper_even_odd: pftClip = ClipperLib::pftEvenOdd; break; case clipper_even_odd: pftClip = ClipperLib::pftEvenOdd; break;
case clipper_non_zero: pftClip = ClipperLib::pftNonZero; break; case clipper_non_zero: pftClip = ClipperLib::pftNonZero; break;
case clipper_positive: pftClip = ClipperLib::pftPositive; break; case clipper_positive: pftClip = ClipperLib::pftPositive; break;
default: pftClip = ClipperLib::pftNegative; default: pftClip = ClipperLib::pftNegative;
} }
m_clipper.Clear(); m_clipper.Clear();
switch( m_operation ) { switch( m_operation ) {
case clipper_or: case clipper_or:
{ {
m_clipper.AddPolygons( m_poly_a , ClipperLib::ptSubject ); m_clipper.AddPolygons( m_poly_a , ClipperLib::ptSubject );
m_clipper.AddPolygons( m_poly_b , ClipperLib::ptClip ); m_clipper.AddPolygons( m_poly_b , ClipperLib::ptClip );
m_clipper.Execute( ClipperLib::ctUnion , m_result , pftSubj, pftClip); m_clipper.Execute( ClipperLib::ctUnion , m_result , pftSubj, pftClip);
break; break;
} }
case clipper_and: case clipper_and:
{ {
m_clipper.AddPolygons( m_poly_a , ClipperLib::ptSubject ); m_clipper.AddPolygons( m_poly_a , ClipperLib::ptSubject );
m_clipper.AddPolygons( m_poly_b , ClipperLib::ptClip ); m_clipper.AddPolygons( m_poly_b , ClipperLib::ptClip );
m_clipper.Execute( ClipperLib::ctIntersection , m_result, pftSubj, pftClip ); m_clipper.Execute( ClipperLib::ctIntersection , m_result, pftSubj, pftClip );
break; break;
} }
case clipper_xor: case clipper_xor:
{ {
m_clipper.AddPolygons( m_poly_a , ClipperLib::ptSubject ); m_clipper.AddPolygons( m_poly_a , ClipperLib::ptSubject );
m_clipper.AddPolygons( m_poly_b , ClipperLib::ptClip ); m_clipper.AddPolygons( m_poly_b , ClipperLib::ptClip );
m_clipper.Execute( ClipperLib::ctXor , m_result, pftSubj, pftClip ); m_clipper.Execute( ClipperLib::ctXor , m_result, pftSubj, pftClip );
break; break;
} }
case clipper_a_minus_b: case clipper_a_minus_b:
{ {
m_clipper.AddPolygons( m_poly_a , ClipperLib::ptSubject ); m_clipper.AddPolygons( m_poly_a , ClipperLib::ptSubject );
m_clipper.AddPolygons( m_poly_b , ClipperLib::ptClip ); m_clipper.AddPolygons( m_poly_b , ClipperLib::ptClip );
m_clipper.Execute( ClipperLib::ctDifference , m_result, pftSubj, pftClip ); m_clipper.Execute( ClipperLib::ctDifference , m_result, pftSubj, pftClip );
break; break;
} }
case clipper_b_minus_a: case clipper_b_minus_a:
{ {
m_clipper.AddPolygons( m_poly_b , ClipperLib::ptSubject ); m_clipper.AddPolygons( m_poly_b , ClipperLib::ptSubject );
m_clipper.AddPolygons( m_poly_a , ClipperLib::ptClip ); m_clipper.AddPolygons( m_poly_a , ClipperLib::ptClip );
m_clipper.Execute( ClipperLib::ctDifference , m_result, pftSubj, pftClip ); m_clipper.Execute( ClipperLib::ctDifference , m_result, pftSubj, pftClip );
break; break;
} }
} }
start_extracting(); start_extracting();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template<class VSA, class VSB> template<class VSA, class VSB>
void conv_clipper<VSA, VSB>::end_contour( ClipperLib::Polygons &p) void conv_clipper<VSA, VSB>::end_contour( ClipperLib::Polygons &p)
{ {
unsigned i, len; unsigned i, len;
if( m_vertex_accumulator.size() < 3 ) return; if( m_vertex_accumulator.size() < 3 ) return;
len = p.size(); len = p.size();
p.resize(len+1); p.resize(len+1);
p[len].resize(m_vertex_accumulator.size()); p[len].resize(m_vertex_accumulator.size());
for( i = 0 ; i < m_vertex_accumulator.size() ; i++ ) for( i = 0 ; i < m_vertex_accumulator.size() ; i++ )
p[len][i] = m_vertex_accumulator[i]; p[len][i] = m_vertex_accumulator[i];
m_vertex_accumulator.remove_all(); m_vertex_accumulator.remove_all();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template<class VSA, class VSB> template<class VSA, class VSB>
void conv_clipper<VSA, VSB>::add_vertex_(double &x, double &y) void conv_clipper<VSA, VSB>::add_vertex_(double &x, double &y)
{ {
ClipperLib::IntPoint v; ClipperLib::IntPoint v;
v.X = Round(x * m_scaling_factor); v.X = Round(x * m_scaling_factor);
v.Y = Round(y * m_scaling_factor); v.Y = Round(y * m_scaling_factor);
m_vertex_accumulator.add( v ); m_vertex_accumulator.add( v );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template<class VSA, class VSB> template<class VSA, class VSB>
bool conv_clipper<VSA, VSB>::next_contour() bool conv_clipper<VSA, VSB>::next_contour()
{ {
m_contour++; m_contour++;
if(m_contour >= (int)m_result.size()) return false; if(m_contour >= (int)m_result.size()) return false;
m_vertex =-1; m_vertex =-1;
return true; return true;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template<class VSA, class VSB> template<class VSA, class VSB>
bool conv_clipper<VSA, VSB>::next_vertex(double *x, double *y) bool conv_clipper<VSA, VSB>::next_vertex(double *x, double *y)
{ {
m_vertex++; m_vertex++;
if(m_vertex >= (int)m_result[m_contour].size()) return false; if(m_vertex >= (int)m_result[m_contour].size()) return false;
*x = (double)m_result[ m_contour ][ m_vertex ].X / m_scaling_factor; *x = (double)m_result[ m_contour ][ m_vertex ].X / m_scaling_factor;
*y = (double)m_result[ m_contour ][ m_vertex ].Y / m_scaling_factor; *y = (double)m_result[ m_contour ][ m_vertex ].Y / m_scaling_factor;
return true; return true;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//------------------------------------------------------------------------------
template<class VSA, class VSB> template<class VSA, class VSB>
unsigned conv_clipper<VSA, VSB>::vertex(double *x, double *y) unsigned conv_clipper<VSA, VSB>::vertex(double *x, double *y)
{ {
if( m_status == status_move_to ) if( m_status == status_move_to )
{ {
if( next_contour() ) if( next_contour() )
{ {
if( next_vertex( x, y ) ) if( next_vertex( x, y ) )
{ {
m_status =status_line_to; m_status =status_line_to;
return path_cmd_move_to; start_x_ = *x;
} start_y_ = *y;
else return path_cmd_move_to;
{ }
m_status = status_stop; else
return path_cmd_end_poly | path_flags_close; {
} *x = start_x_;
} *y = start_y_;
else m_status = status_stop;
return path_cmd_stop; return path_cmd_end_poly | path_flags_close;
} }
else }
{ else
if( next_vertex( x, y ) ) return path_cmd_stop;
{ }
return path_cmd_line_to; else
} {
else if( next_vertex( x, y ) )
{ {
m_status = status_move_to; return path_cmd_line_to;
return path_cmd_end_poly | path_flags_close; }
} else
} {
m_status = status_move_to;
*x = start_x_;
*y = start_y_;
return path_cmd_end_poly | path_flags_close;
}
}
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------