# qwt_rect.cpp

    00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
    00002  * Qwt Widget Library
    00003  * Copyright (C) 1997   Josef Wilgen
    00004  * Copyright (C) 2002   Uwe Rathmann
    00005  *
    00006  * This library is free software; you can redistribute it and/or
    00007  * modify it under the terms of the Qwt License, Version 1.0
    00008  *****************************************************************************/
    00009
    00010 #include "qwt_math.h"
    00011 #include "qwt_rect.h"
    00012
    00014
    00015 QwtRect::QwtRect():
    00016     QRect()
    00017 {
    00018 }
    00019
    00021 QwtRect::QwtRect(const QRect &r):
    00022     QRect(r)
    00023 {
    00024 }
    00025
    00026 inline static void addPoint(QwtPolygon &pa, uint pos, const QPoint &point)
    00027 {
    00028     if ( uint(pa.size()) <= pos )
    00029         pa.resize(pos + 5);
    00030
    00031     pa.setPoint(pos, point);
    00032 }
    00033
    00035
    00036 QwtPolygon QwtRect::clip(const QwtPolygon &pa) const
    00037 {
    00038     if ( contains( pa.boundingRect() ) )
    00039         return pa;
    00040
    00041     QwtPolygon cpa(pa.size());
    00042
    00043     clipEdge((Edge)0, pa, cpa);
    00044
    00045     for ( uint edge = 1; edge < NEdges; edge++ )
    00046     {
    00047         const QwtPolygon rpa = cpa;
    00048 #if QT_VERSION < 0x040000
    00049         cpa.detach();
    00050 #endif
    00051         clipEdge((Edge)edge, rpa, cpa);
    00052     }
    00053
    00054     return cpa;
    00055 }
    00056
    00057 bool QwtRect::insideEdge(const QPoint &p, Edge edge) const
    00058 {
    00059     switch(edge)
    00060     {
    00061         case Left:
    00062             return p.x() > left();
    00063         case Top:
    00064             return p.y() > top();
    00065         case Right:
    00066             return p.x() < right();
    00067         case Bottom:
    00068             return p.y() < bottom();
    00069         default:
    00070             break;
    00071     }
    00072
    00073     return false;
    00074 }
    00075
    00076 QPoint QwtRect::intersectEdge(const QPoint &p1,
    00077     const QPoint &p2, Edge edge ) const
    00078 {
    00079     int x=0, y=0;
    00080     double m = 0;
    00081
    00082     const double dy = p2.y() - p1.y();
    00083     const double dx = p2.x() - p1.x();
    00084
    00085     switch ( edge )
    00086     {
    00087         case Left:
    00088             x = left();
    00089             m = double(qwtAbs(p1.x() - x)) / qwtAbs(dx);
    00090             y = p1.y() + int(dy * m);
    00091             break;
    00092         case Top:
    00093             y = top();
    00094             m = double(qwtAbs(p1.y() - y)) / qwtAbs(dy);
    00095             x = p1.x() + int(dx * m);
    00096             break;
    00097         case Right:
    00098             x = right();
    00099             m = double(qwtAbs(p1.x() - x)) / qwtAbs(dx);
    00100             y = p1.y() + int(dy * m);
    00101             break;
    00102         case Bottom:
    00103             y = bottom();
    00104             m = double(qwtAbs(p1.y() - y)) / qwtAbs(dy);
    00105             x = p1.x() + int(dx * m);
    00106             break;
    00107         default:
    00108             break;
    00109     }
    00110
    00111     return QPoint(x,y);
    00112 }
    00113
    00114 void QwtRect::clipEdge(Edge edge,
    00115     const QwtPolygon &pa, QwtPolygon &cpa) const
    00116 {
    00117     if ( pa.count() == 0 )
    00118     {
    00119         cpa.resize(0);
    00120         return;
    00121     }
    00122
    00123     unsigned int count = 0;
    00124
    00125     QPoint p1 = pa.point(0);
    00126     if ( insideEdge(p1, edge) )
    00127         addPoint(cpa, count++, p1);
    00128
    00129     const uint nPoints = pa.size();
    00130     for ( uint i = 1; i < nPoints; i++ )
    00131     {
    00132         const QPoint p2 = pa.point(i);
    00133         if ( insideEdge(p2, edge) )
    00134         {
    00135             if ( insideEdge(p1, edge) )
    00136                 addPoint(cpa, count++, p2);
    00137             else
    00138             {
    00139                 addPoint(cpa, count++, intersectEdge(p1, p2, edge));
    00140                 addPoint(cpa, count++, p2);
    00141             }
    00142         }
    00143         else
    00144         {
    00145             if ( insideEdge(p1, edge) )
    00146                 addPoint(cpa, count++, intersectEdge(p1, p2, edge));
    00147         }
    00148         p1 = p2;
    00149     }
    00150     cpa.resize(count);
    00151 }