2011-10-12 03:02:50 +00:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
// Anti-Grain Geometry - Version 2.4
|
|
|
|
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
|
|
|
//
|
2013-02-12 15:51:40 +00:00
|
|
|
// Permission to copy, use, modify, sell and distribute this software
|
|
|
|
// is granted provided this copyright notice appears in all copies.
|
2011-10-12 03:02:50 +00:00
|
|
|
// This software is provided "as is" without express or implied
|
|
|
|
// warranty, and with no claim as to its suitability for any purpose.
|
|
|
|
//
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
// Contact: mcseem@antigrain.com
|
|
|
|
// mcseemagg@yahoo.com
|
|
|
|
// http://www.antigrain.com
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
//
|
2013-02-12 15:51:40 +00:00
|
|
|
// Liang-Barsky clipping
|
2011-10-12 03:02:50 +00:00
|
|
|
//
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
#ifndef AGG_CLIP_LIANG_BARSKY_INCLUDED
|
|
|
|
#define AGG_CLIP_LIANG_BARSKY_INCLUDED
|
|
|
|
|
|
|
|
#include "agg_basics.h"
|
|
|
|
|
|
|
|
namespace agg
|
|
|
|
{
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
enum clipping_flags_e
|
|
|
|
{
|
|
|
|
clipping_flags_x1_clipped = 4,
|
|
|
|
clipping_flags_x2_clipped = 1,
|
|
|
|
clipping_flags_y1_clipped = 8,
|
|
|
|
clipping_flags_y2_clipped = 2,
|
|
|
|
clipping_flags_x_clipped = clipping_flags_x1_clipped | clipping_flags_x2_clipped,
|
|
|
|
clipping_flags_y_clipped = clipping_flags_y1_clipped | clipping_flags_y2_clipped
|
|
|
|
};
|
|
|
|
|
|
|
|
//----------------------------------------------------------clipping_flags
|
2013-02-12 15:51:40 +00:00
|
|
|
// Determine the clipping code of the vertex according to the
|
2011-10-12 03:02:50 +00:00
|
|
|
// Cyrus-Beck line clipping algorithm
|
|
|
|
//
|
|
|
|
// | |
|
|
|
|
// 0110 | 0010 | 0011
|
|
|
|
// | |
|
|
|
|
// -------+--------+-------- clip_box.y2
|
|
|
|
// | |
|
|
|
|
// 0100 | 0000 | 0001
|
|
|
|
// | |
|
|
|
|
// -------+--------+-------- clip_box.y1
|
|
|
|
// | |
|
|
|
|
// 1100 | 1000 | 1001
|
|
|
|
// | |
|
|
|
|
// clip_box.x1 clip_box.x2
|
|
|
|
//
|
2013-02-12 15:51:40 +00:00
|
|
|
//
|
2011-10-12 03:02:50 +00:00
|
|
|
template<class T>
|
|
|
|
inline unsigned clipping_flags(T x, T y, const rect_base<T>& clip_box)
|
|
|
|
{
|
|
|
|
return (x > clip_box.x2) |
|
|
|
|
((y > clip_box.y2) << 1) |
|
|
|
|
((x < clip_box.x1) << 2) |
|
|
|
|
((y < clip_box.y1) << 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------clipping_flags_x
|
|
|
|
template<class T>
|
|
|
|
inline unsigned clipping_flags_x(T x, const rect_base<T>& clip_box)
|
|
|
|
{
|
|
|
|
return (x > clip_box.x2) | ((x < clip_box.x1) << 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------clipping_flags_y
|
|
|
|
template<class T>
|
|
|
|
inline unsigned clipping_flags_y(T y, const rect_base<T>& clip_box)
|
|
|
|
{
|
|
|
|
return ((y > clip_box.y2) << 1) | ((y < clip_box.y1) << 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------clip_liang_barsky
|
|
|
|
template<class T>
|
|
|
|
inline unsigned clip_liang_barsky(T x1, T y1, T x2, T y2,
|
|
|
|
const rect_base<T>& clip_box,
|
|
|
|
T* x, T* y)
|
|
|
|
{
|
|
|
|
const double nearzero = 1e-30;
|
|
|
|
|
|
|
|
double deltax = x2 - x1;
|
2013-02-12 15:51:40 +00:00
|
|
|
double deltay = y2 - y1;
|
2011-10-12 03:02:50 +00:00
|
|
|
double xin;
|
|
|
|
double xout;
|
|
|
|
double yin;
|
|
|
|
double yout;
|
|
|
|
double tinx;
|
|
|
|
double tiny;
|
|
|
|
double toutx;
|
2013-02-12 15:51:40 +00:00
|
|
|
double touty;
|
2011-10-12 03:02:50 +00:00
|
|
|
double tin1;
|
|
|
|
double tin2;
|
|
|
|
double tout1;
|
|
|
|
unsigned np = 0;
|
|
|
|
|
2013-02-12 15:51:40 +00:00
|
|
|
if(deltax == 0.0)
|
|
|
|
{
|
2011-10-12 03:02:50 +00:00
|
|
|
// bump off of the vertical
|
|
|
|
deltax = (x1 > clip_box.x1) ? -nearzero : nearzero;
|
|
|
|
}
|
|
|
|
|
2013-02-12 15:51:40 +00:00
|
|
|
if(deltay == 0.0)
|
|
|
|
{
|
|
|
|
// bump off of the horizontal
|
2011-10-12 03:02:50 +00:00
|
|
|
deltay = (y1 > clip_box.y1) ? -nearzero : nearzero;
|
|
|
|
}
|
2013-02-12 15:51:40 +00:00
|
|
|
|
|
|
|
if(deltax > 0.0)
|
|
|
|
{
|
2011-10-12 03:02:50 +00:00
|
|
|
// points to right
|
|
|
|
xin = clip_box.x1;
|
|
|
|
xout = clip_box.x2;
|
|
|
|
}
|
2013-02-12 15:51:40 +00:00
|
|
|
else
|
2011-10-12 03:02:50 +00:00
|
|
|
{
|
|
|
|
xin = clip_box.x2;
|
|
|
|
xout = clip_box.x1;
|
|
|
|
}
|
|
|
|
|
2013-02-12 15:51:40 +00:00
|
|
|
if(deltay > 0.0)
|
2011-10-12 03:02:50 +00:00
|
|
|
{
|
|
|
|
// points up
|
|
|
|
yin = clip_box.y1;
|
|
|
|
yout = clip_box.y2;
|
|
|
|
}
|
2013-02-12 15:51:40 +00:00
|
|
|
else
|
2011-10-12 03:02:50 +00:00
|
|
|
{
|
|
|
|
yin = clip_box.y2;
|
|
|
|
yout = clip_box.y1;
|
|
|
|
}
|
2013-02-12 15:51:40 +00:00
|
|
|
|
2011-10-12 03:02:50 +00:00
|
|
|
tinx = (xin - x1) / deltax;
|
|
|
|
tiny = (yin - y1) / deltay;
|
2013-02-12 15:51:40 +00:00
|
|
|
|
|
|
|
if (tinx < tiny)
|
2011-10-12 03:02:50 +00:00
|
|
|
{
|
|
|
|
// hits x first
|
|
|
|
tin1 = tinx;
|
|
|
|
tin2 = tiny;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// hits y first
|
|
|
|
tin1 = tiny;
|
|
|
|
tin2 = tinx;
|
|
|
|
}
|
2013-02-12 15:51:40 +00:00
|
|
|
|
|
|
|
if(tin1 <= 1.0)
|
2011-10-12 03:02:50 +00:00
|
|
|
{
|
2013-02-12 15:51:40 +00:00
|
|
|
if(0.0 < tin1)
|
2011-10-12 03:02:50 +00:00
|
|
|
{
|
|
|
|
*x++ = (T)xin;
|
|
|
|
*y++ = (T)yin;
|
|
|
|
++np;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(tin2 <= 1.0)
|
|
|
|
{
|
|
|
|
toutx = (xout - x1) / deltax;
|
|
|
|
touty = (yout - y1) / deltay;
|
2013-02-12 15:51:40 +00:00
|
|
|
|
2011-10-12 03:02:50 +00:00
|
|
|
tout1 = (toutx < touty) ? toutx : touty;
|
2013-02-12 15:51:40 +00:00
|
|
|
|
|
|
|
if(tin2 > 0.0 || tout1 > 0.0)
|
2011-10-12 03:02:50 +00:00
|
|
|
{
|
2013-02-12 15:51:40 +00:00
|
|
|
if(tin2 <= tout1)
|
2011-10-12 03:02:50 +00:00
|
|
|
{
|
2013-02-12 15:51:40 +00:00
|
|
|
if(tin2 > 0.0)
|
2011-10-12 03:02:50 +00:00
|
|
|
{
|
2013-02-12 15:51:40 +00:00
|
|
|
if(tinx > tiny)
|
2011-10-12 03:02:50 +00:00
|
|
|
{
|
|
|
|
*x++ = (T)xin;
|
|
|
|
*y++ = (T)(y1 + tinx * deltay);
|
|
|
|
}
|
2013-02-12 15:51:40 +00:00
|
|
|
else
|
2011-10-12 03:02:50 +00:00
|
|
|
{
|
|
|
|
*x++ = (T)(x1 + tiny * deltax);
|
|
|
|
*y++ = (T)yin;
|
|
|
|
}
|
|
|
|
++np;
|
|
|
|
}
|
|
|
|
|
2013-02-12 15:51:40 +00:00
|
|
|
if(tout1 < 1.0)
|
2011-10-12 03:02:50 +00:00
|
|
|
{
|
2013-02-12 15:51:40 +00:00
|
|
|
if(toutx < touty)
|
2011-10-12 03:02:50 +00:00
|
|
|
{
|
|
|
|
*x++ = (T)xout;
|
|
|
|
*y++ = (T)(y1 + toutx * deltay);
|
|
|
|
}
|
2013-02-12 15:51:40 +00:00
|
|
|
else
|
2011-10-12 03:02:50 +00:00
|
|
|
{
|
|
|
|
*x++ = (T)(x1 + touty * deltax);
|
|
|
|
*y++ = (T)yout;
|
|
|
|
}
|
|
|
|
}
|
2013-02-20 14:11:07 +00:00
|
|
|
else
|
2011-10-12 03:02:50 +00:00
|
|
|
{
|
|
|
|
*x++ = x2;
|
|
|
|
*y++ = y2;
|
|
|
|
}
|
2013-02-20 14:11:07 +00:00
|
|
|
++np;
|
2011-10-12 03:02:50 +00:00
|
|
|
}
|
2013-02-12 15:51:40 +00:00
|
|
|
else
|
2011-10-12 03:02:50 +00:00
|
|
|
{
|
2013-02-12 15:51:40 +00:00
|
|
|
if(tinx > tiny)
|
2011-10-12 03:02:50 +00:00
|
|
|
{
|
|
|
|
*x++ = (T)xin;
|
|
|
|
*y++ = (T)yout;
|
|
|
|
}
|
2013-02-12 15:51:40 +00:00
|
|
|
else
|
2011-10-12 03:02:50 +00:00
|
|
|
{
|
|
|
|
*x++ = (T)xout;
|
|
|
|
*y++ = (T)yin;
|
|
|
|
}
|
|
|
|
++np;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return np;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
template<class T>
|
2013-02-12 15:51:40 +00:00
|
|
|
bool clip_move_point(T x1, T y1, T x2, T y2,
|
|
|
|
const rect_base<T>& clip_box,
|
2011-10-12 03:02:50 +00:00
|
|
|
T* x, T* y, unsigned flags)
|
|
|
|
{
|
|
|
|
T bound;
|
|
|
|
|
|
|
|
if(flags & clipping_flags_x_clipped)
|
|
|
|
{
|
|
|
|
if(x1 == x2)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
bound = (flags & clipping_flags_x1_clipped) ? clip_box.x1 : clip_box.x2;
|
|
|
|
*y = (T)(double(bound - x1) * (y2 - y1) / (x2 - x1) + y1);
|
|
|
|
*x = bound;
|
|
|
|
}
|
|
|
|
|
|
|
|
flags = clipping_flags_y(*y, clip_box);
|
|
|
|
if(flags & clipping_flags_y_clipped)
|
|
|
|
{
|
|
|
|
if(y1 == y2)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
bound = (flags & clipping_flags_y1_clipped) ? clip_box.y1 : clip_box.y2;
|
|
|
|
*x = (T)(double(bound - y1) * (x2 - x1) / (y2 - y1) + x1);
|
|
|
|
*y = bound;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------clip_line_segment
|
|
|
|
// Returns: ret >= 4 - Fully clipped
|
|
|
|
// (ret & 1) != 0 - First point has been moved
|
|
|
|
// (ret & 2) != 0 - Second point has been moved
|
|
|
|
//
|
|
|
|
template<class T>
|
|
|
|
unsigned clip_line_segment(T* x1, T* y1, T* x2, T* y2,
|
|
|
|
const rect_base<T>& clip_box)
|
|
|
|
{
|
|
|
|
unsigned f1 = clipping_flags(*x1, *y1, clip_box);
|
|
|
|
unsigned f2 = clipping_flags(*x2, *y2, clip_box);
|
|
|
|
unsigned ret = 0;
|
|
|
|
|
|
|
|
if((f2 | f1) == 0)
|
|
|
|
{
|
|
|
|
// Fully visible
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-02-12 15:51:40 +00:00
|
|
|
if((f1 & clipping_flags_x_clipped) != 0 &&
|
2011-10-12 03:02:50 +00:00
|
|
|
(f1 & clipping_flags_x_clipped) == (f2 & clipping_flags_x_clipped))
|
|
|
|
{
|
|
|
|
// Fully clipped
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
|
2013-02-12 15:51:40 +00:00
|
|
|
if((f1 & clipping_flags_y_clipped) != 0 &&
|
2011-10-12 03:02:50 +00:00
|
|
|
(f1 & clipping_flags_y_clipped) == (f2 & clipping_flags_y_clipped))
|
|
|
|
{
|
|
|
|
// Fully clipped
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
T tx1 = *x1;
|
|
|
|
T ty1 = *y1;
|
|
|
|
T tx2 = *x2;
|
|
|
|
T ty2 = *y2;
|
2013-02-12 15:51:40 +00:00
|
|
|
if(f1)
|
|
|
|
{
|
|
|
|
if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x1, y1, f1))
|
2011-10-12 03:02:50 +00:00
|
|
|
{
|
|
|
|
return 4;
|
|
|
|
}
|
2013-02-12 15:51:40 +00:00
|
|
|
if(*x1 == *x2 && *y1 == *y2)
|
2011-10-12 03:02:50 +00:00
|
|
|
{
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
ret |= 1;
|
|
|
|
}
|
2013-02-12 15:51:40 +00:00
|
|
|
if(f2)
|
2011-10-12 03:02:50 +00:00
|
|
|
{
|
|
|
|
if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x2, y2, f2))
|
|
|
|
{
|
|
|
|
return 4;
|
|
|
|
}
|
2013-02-12 15:51:40 +00:00
|
|
|
if(*x1 == *x2 && *y1 == *y2)
|
2011-10-12 03:02:50 +00:00
|
|
|
{
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
ret |= 2;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|