10 #include "qwt_clipper.h" 
   11 #include "qwt_point_polar.h" 
   12 #include "qwt_interval.h" 
   23     template< 
class Po
int, 
typename T > 
class LeftEdge;
 
   24     template< 
class Po
int, 
typename T > 
class RightEdge;
 
   25     template< 
class Po
int, 
typename T > 
class TopEdge;
 
   26     template< 
class Po
int, 
typename T > 
class BottomEdge;
 
   29 template< 
class Po
int, 
typename Value >
 
   30 class QwtClip::LeftEdge
 
   33     inline LeftEdge( Value x1, Value, Value, Value ):
 
   38     inline bool isInside( 
const Point& p  )
 const 
   43     inline Point intersection( 
const Point& p1, 
const Point& p2 )
 const 
   45         double dy = ( p1.y() - p2.y() ) / 
double( p1.x() - p2.x() );
 
   46         return Point( m_x1, 
static_cast< Value 
>( p2.y() + ( m_x1 - p2.x() ) * dy ) );
 
   52 template< 
class Po
int, 
typename Value >
 
   53 class QwtClip::RightEdge
 
   56     inline RightEdge( Value, Value x2, Value, Value ):
 
   61     inline bool isInside( 
const Point& p  )
 const 
   66     inline Point intersection( 
const Point& p1, 
const Point& p2 )
 const 
   68         double dy = ( p1.y() - p2.y() ) / 
double( p1.x() - p2.x() );
 
   69         return Point( m_x2, 
static_cast< Value 
>( p2.y() + ( m_x2 - p2.x() ) * dy ) );
 
   76 template< 
class Po
int, 
typename Value >
 
   77 class QwtClip::TopEdge
 
   80     inline TopEdge( Value, Value, Value y1, Value ):
 
   85     inline bool isInside( 
const Point& p  )
 const 
   90     inline Point intersection( 
const Point& p1, 
const Point& p2 )
 const 
   92         double dx = ( p1.x() - p2.x() ) / 
double( p1.y() - p2.y() );
 
   93         return Point( 
static_cast< Value 
>( p2.x() + ( m_y1 - p2.y() ) * dx ), m_y1 );
 
  100 template< 
class Po
int, 
typename Value >
 
  101 class QwtClip::BottomEdge
 
  104     inline BottomEdge( Value, Value, Value, Value y2 ):
 
  109     inline bool isInside( 
const Point& p )
 const 
  111         return p.y() <= m_y2;
 
  114     inline Point intersection( 
const Point& p1, 
const Point& p2 )
 const 
  116         double dx = ( p1.x() - p2.x() ) / 
double( p1.y() - p2.y() );
 
  117         return Point( 
static_cast< Value 
>( p2.x() + ( m_y2 - p2.y() ) * dx ), m_y2 );
 
  124 using namespace QwtClip;
 
  126 template< 
class Polygon, 
class Rect, 
typename T >
 
  127 class QwtPolygonClipper
 
  129     typedef typename Polygon::value_type Point;
 
  131     explicit QwtPolygonClipper( 
const Rect& clipRect ):
 
  132         m_clipRect( clipRect )
 
  136     void clipPolygon( Polygon& points1, 
bool closePolygon )
 const 
  139         if ( m_clipRect.contains( points1.boundingRect() ) )
 
  144         points2.reserve( qMin( 256, points1.size() ) );
 
  146         clipEdge< LeftEdge< Point, T > >( closePolygon, points1, points2 );
 
  147         clipEdge< RightEdge< Point, T > >( closePolygon, points2, points1 );
 
  148         clipEdge< TopEdge< Point, T > >( closePolygon, points1, points2 );
 
  149         clipEdge< BottomEdge< Point, T > >( closePolygon, points2, points1 );
 
  153     template< 
class Edge >
 
  154     inline void clipEdge( 
bool closePolygon,
 
  155         const Polygon& points, Polygon& clippedPoints )
 const 
  157         clippedPoints.clear();
 
  159         if ( points.size() < 2 )
 
  161             if ( points.size() == 1 )
 
  162                 clippedPoints += points[0];
 
  167         const Edge edge( m_clipRect.x(), m_clipRect.x() + m_clipRect.width(),
 
  168             m_clipRect.y(), m_clipRect.y() + m_clipRect.height() );
 
  172             const Point& p1 = points.first();
 
  174             if ( edge.isInside( p1 ) )
 
  179             const Point& p1 = points.first();
 
  180             const Point& p2 = points.last();
 
  182             if ( edge.isInside( p1 ) )
 
  184                 if ( !edge.isInside( p2 ) )
 
  185                     clippedPoints += edge.intersection( p1, p2 );
 
  189             else if ( edge.isInside( p2 ) )
 
  191                 clippedPoints += edge.intersection( p1, p2 );
 
  195         const uint nPoints = points.size();
 
  196         const Point* p = points.constData();
 
  198         for ( uint i = 1; i < nPoints; i++ )
 
  200             const Point& p1 = p[i];
 
  201             const Point& p2 = p[i - 1];
 
  203             if ( edge.isInside( p1 ) )
 
  205                 if ( !edge.isInside( p2 ) )
 
  206                     clippedPoints += edge.intersection( p1, p2 );
 
  210             else if ( edge.isInside( p2 ) )
 
  212                 clippedPoints += edge.intersection( p1, p2 );
 
  217     const Rect m_clipRect;
 
  220 class QwtCircleClipper
 
  223     explicit QwtCircleClipper( 
const QRectF& r );
 
  238         Edge, 
const QPointF& pos, 
double radius ) 
const;
 
  240     double toAngle( 
const QPointF&, 
const QPointF& ) 
const;
 
  246 QwtCircleClipper::QwtCircleClipper( 
const QRectF& r )
 
  252     const QPointF& pos, 
double radius )
 const 
  257     for ( 
int edge = 0; edge < NEdges; edge++ )
 
  258         points += cuttingPoints( 
static_cast< Edge 
>( edge ), pos, radius );
 
  261     if ( points.size() <= 0 )
 
  263         QRectF cRect( 0, 0, 2 * radius, 2 * radius );
 
  264         cRect.moveCenter( pos );
 
  265         if ( m_rect.contains( cRect ) )
 
  271         angles.reserve( points.size() );
 
  273         for ( 
int i = 0; i < points.size(); i++ )
 
  274             angles += toAngle( pos, points[i] );
 
  276         std::sort( angles.begin(), angles.end() );
 
  278         const int in = m_rect.contains( qwtPolar2Pos( pos, radius,
 
  279             angles[0] + ( angles[1] - angles[0] ) / 2 ) );
 
  281         intv.reserve( angles.size() / 2 );
 
  284             for ( 
int i = 0; i < angles.size() - 1; i += 2 )
 
  289             for ( 
int i = 1; i < angles.size() - 1; i += 2 )
 
  292             intv += 
QwtInterval( angles.last(), angles.first() );
 
  299 double QwtCircleClipper::toAngle(
 
  300     const QPointF& from, 
const QPointF& to )
 const 
  302     if ( from.x() == to.x() )
 
  303         return from.y() <= to.y() ? M_PI / 2.0 : 3 * M_PI / 2.0;
 
  305     const double m = qAbs( ( to.y() - from.y() ) / ( to.x() - from.x() ) );
 
  307     double angle = std::atan( m );
 
  308     if ( to.x() > from.x() )
 
  310         if ( to.y() > from.y() )
 
  311             angle = 2 * M_PI - angle;
 
  315         if ( to.y() > from.y() )
 
  316             angle = M_PI + angle;
 
  318             angle = M_PI - angle;
 
  325     Edge edge, 
const QPointF& pos, 
double radius )
 const 
  329     if ( edge == Left || edge == Right )
 
  331         const double x = ( edge == Left ) ? m_rect.left() : m_rect.right();
 
  332         if ( qAbs( pos.x() - x ) < radius )
 
  334             const double off = std::sqrt( qwtSqr( radius ) - qwtSqr( pos.x() - x ) );
 
  335             const double m_y1 = pos.y() + off;
 
  336             if ( m_y1 >= m_rect.top() && m_y1 <= m_rect.bottom() )
 
  337                 points += QPointF( x, m_y1 );
 
  339             const double m_y2 = pos.y() - off;
 
  340             if ( m_y2 >= m_rect.top() && m_y2 <= m_rect.bottom() )
 
  341                 points += QPointF( x, m_y2 );
 
  346         const double y = ( edge == Top ) ? m_rect.top() : m_rect.bottom();
 
  347         if ( qAbs( pos.y() - y ) < radius )
 
  349             const double off = std::sqrt( qwtSqr( radius ) - qwtSqr( pos.y() - y ) );
 
  350             const double x1 = pos.x() + off;
 
  351             if ( x1 >= m_rect.left() && x1 <= m_rect.right() )
 
  352                 points += QPointF( x1, y );
 
  354             const double m_x2 = pos.x() - off;
 
  355             if ( m_x2 >= m_rect.left() && m_x2 <= m_rect.right() )
 
  356                 points += QPointF( m_x2, y );
 
  370     const QRectF& clipRect, QPolygon& polygon, 
bool closePolygon )
 
  372     const int minX = qCeil( clipRect.left() );
 
  373     const int maxX = qFloor( clipRect.right() );
 
  374     const int minY = qCeil( clipRect.top() );
 
  375     const int maxY = qFloor( clipRect.bottom() );
 
  377     const QRect r( minX, minY, maxX - minX, maxY - minY );
 
  379     QwtPolygonClipper< QPolygon, QRect, int > clipper( r );
 
  380     clipper.clipPolygon( polygon, closePolygon );
 
  391     const QRect& clipRect, QPolygon& polygon, 
bool closePolygon )
 
  393     QwtPolygonClipper< QPolygon, QRect, int > clipper( clipRect );
 
  394     clipper.clipPolygon( polygon, closePolygon );
 
  405     const QRectF& clipRect, QPolygonF& polygon, 
bool closePolygon )
 
  407     QwtPolygonClipper< QPolygonF, QRectF, double > clipper( clipRect );
 
  408     clipper.clipPolygon( polygon, closePolygon );
 
  421     const QRectF& clipRect, 
const QPolygon& polygon, 
bool closePolygon )
 
  423     QPolygon points( polygon );
 
  438     const QRect& clipRect, 
const QPolygon& polygon, 
bool closePolygon )
 
  440     QPolygon points( polygon );
 
  456     const QRectF& clipRect, 
const QPolygonF& polygon, 
bool closePolygon )
 
  458     QPolygonF points( polygon );
 
  478     const QPointF& center, 
double radius )
 
  480     QwtCircleClipper clipper( clipRect );
 
  481     return clipper.clipCircle( center, radius );
 
A class representing an interval.
QWT_EXPORT void clipPolygon(const QRect &, QPolygon &, bool closePolygon=false)
QWT_EXPORT QPolygonF clippedPolygonF(const QRectF &, const QPolygonF &, bool closePolygon=false)
QWT_EXPORT void clipPolygonF(const QRectF &, QPolygonF &, bool closePolygon=false)
QWT_EXPORT QVector< QwtInterval > clipCircle(const QRectF &, const QPointF &, double radius)
QWT_EXPORT QPolygon clippedPolygon(const QRect &, const QPolygon &, bool closePolygon=false)