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;
29template<
class Po
int,
typename Value >
30class 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 ) );
52template<
class Po
int,
typename Value >
53class 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 ) );
76template<
class Po
int,
typename Value >
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 );
100template<
class Po
int,
typename Value >
101class 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 );
124using namespace QwtClip;
126template<
class Polygon,
class Rect,
typename T >
127class 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;
220class QwtCircleClipper
223 explicit QwtCircleClipper(
const QRectF& r );
238 Edge,
const QPointF& pos,
double radius )
const;
240 double toAngle(
const QPointF&,
const QPointF& )
const;
246QwtCircleClipper::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() );
299double 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)