00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "qwt_math.h"
00011 #include "qwt_rect.h"
00012
00013 #if QT_VERSION < 0x040000
00014 #define QwtPointArray QPointArray
00015 #else
00016 #define QwtPointArray QPolygon
00017 #endif
00018
00020
00021 QwtRect::QwtRect():
00022 QRect()
00023 {
00024 }
00025
00027 QwtRect::QwtRect(const QRect &r):
00028 QRect(r)
00029 {
00030 }
00031
00032 QRect QwtRect::cutTop(int h, int distTop, int distBottom)
00033 {
00034 QRect rv;
00035 rv.setTop(top() + distTop);
00036 rv.setHeight(h);
00037 setTop(rv.bottom() + distBottom + 1);
00038 rv.setLeft(left());
00039 rv.setRight(right());
00040 return rv;
00041 }
00042
00043 QRect QwtRect::cutBottom(int h, int distTop, int distBottom)
00044 {
00045 QRect rv;
00046 setBottom(bottom() - h - distBottom - distTop);
00047 rv.setTop(bottom() + 1 + distTop);
00048 rv.setHeight(h);
00049 rv.setLeft(left());
00050 rv.setRight(right());
00051 return rv;
00052 }
00053
00054 QRect QwtRect::cutLeft(int w, int distLeft, int distRight)
00055 {
00056 QRect rv;
00057 rv.setLeft(left() + distLeft);
00058 rv.setWidth(w);
00059 setLeft(rv.right() + distRight + 1);
00060 rv.setTop(top());
00061 rv.setBottom(bottom());
00062 return rv;
00063 }
00064
00065 QRect QwtRect::cutRight(int w, int distLeft, int distRight)
00066 {
00067 QRect rv;
00068 setRight(right() - w - distRight - distLeft);
00069 rv.setLeft(right() + 1 + distLeft);
00070 rv.setWidth(w);
00071 rv.setTop(top());
00072 rv.setBottom(bottom());
00073 return rv;
00074 }
00075
00076 const QwtRect& QwtRect::cutMargin(int mLeft, int mRight, int mTop, int mBottom)
00077 {
00078 setHeight(height() - mTop - mBottom);
00079 setWidth(width() - mLeft - mRight);
00080 #if QT_VERSION < 0x040000
00081 moveBy(mLeft, mTop);
00082 #else
00083 translate(mLeft, mTop);
00084 #endif
00085 return *this;
00086 }
00087
00088 inline void addPoint(QwtPointArray &pa, uint pos, const QPoint &point)
00089 {
00090 if ( uint(pa.size()) <= pos )
00091 pa.resize(pos + 5);
00092
00093 pa.setPoint(pos, point);
00094 }
00095
00097
00098 QwtPointArray QwtRect::clip(const QwtPointArray &pa) const
00099 {
00100 if ( contains( pa.boundingRect() ) )
00101 return pa;
00102
00103 QwtPointArray cpa(pa.size());
00104
00105 clipEdge((Edge)0, pa, cpa);
00106
00107 for ( uint edge = 1; edge < NEdges; edge++ )
00108 {
00109 const QwtPointArray rpa = cpa;
00110 #if QT_VERSION < 0x040000
00111 cpa.detach();
00112 #endif
00113 clipEdge((Edge)edge, rpa, cpa);
00114 }
00115
00116 return cpa;
00117 }
00118
00119 bool QwtRect::insideEdge(const QPoint &p, Edge edge) const
00120 {
00121 switch(edge)
00122 {
00123 case Left:
00124 return p.x() > left();
00125 case Top:
00126 return p.y() > top();
00127 case Right:
00128 return p.x() < right();
00129 case Bottom:
00130 return p.y() < bottom();
00131 default:
00132 break;
00133 }
00134
00135 return false;
00136 }
00137
00138 QPoint QwtRect::intersectEdge(const QPoint &p1,
00139 const QPoint &p2, Edge edge ) const
00140 {
00141 int x=0, y=0;
00142 double m = 0;
00143
00144 const double dy = p2.y() - p1.y();
00145 const double dx = p2.x() - p1.x();
00146
00147 switch ( edge )
00148 {
00149 case Left:
00150 x = left();
00151 m = double(qwtAbs(p1.x() - x)) / qwtAbs(dx);
00152 y = p1.y() + int(dy * m);
00153 break;
00154 case Top:
00155 y = top();
00156 m = double(qwtAbs(p1.y() - y)) / qwtAbs(dy);
00157 x = p1.x() + int(dx * m);
00158 break;
00159 case Right:
00160 x = right();
00161 m = double(qwtAbs(p1.x() - x)) / qwtAbs(dx);
00162 y = p1.y() + int(dy * m);
00163 break;
00164 case Bottom:
00165 y = bottom();
00166 m = double(qwtAbs(p1.y() - y)) / qwtAbs(dy);
00167 x = p1.x() + int(dx * m);
00168 break;
00169 default:
00170 break;
00171 }
00172
00173 return QPoint(x,y);
00174 }
00175
00176 void QwtRect::clipEdge(Edge edge,
00177 const QwtPointArray &pa, QwtPointArray &cpa) const
00178 {
00179 if ( pa.count() == 0 )
00180 {
00181 cpa.resize(0);
00182 return;
00183 }
00184
00185 unsigned int count = 0;
00186
00187 QPoint p1 = pa.point(0);
00188 if ( insideEdge(p1, edge) )
00189 addPoint(cpa, count++, p1);
00190
00191 const uint nPoints = pa.size();
00192 for ( uint i = 1; i < nPoints; i++ )
00193 {
00194 const QPoint p2 = pa.point(i);
00195 if ( insideEdge(p2, edge) )
00196 {
00197 if ( insideEdge(p1, edge) )
00198 addPoint(cpa, count++, p2);
00199 else
00200 {
00201 addPoint(cpa, count++, intersectEdge(p1, p2, edge));
00202 addPoint(cpa, count++, p2);
00203 }
00204 }
00205 else
00206 {
00207 if ( insideEdge(p1, edge) )
00208 addPoint(cpa, count++, intersectEdge(p1, p2, edge));
00209 }
00210 p1 = p2;
00211 }
00212 cpa.resize(count);
00213 }